Open dshanske opened 5 years ago
I think this is definitely needed, not just for experimental properties but also for official ones. Because if Micropub were to become an Evergreen Spec like @aaronpk was thinking through a bit in chat the other day, we would need a way to define what parts people support since you might have older, unsupported endpoints at some point.
I'm interested in this in conjunction with #11. I'm adding visibility
options to indiebookclub. I think it's important that IBC can tell if the mp server supports "private" or "unlisted" before presenting those options in the UI.
So I think there are at least 2 ways we would need to show full support for a property:
summary
and category
can accept pretty much anything, but would be nice to know if they are supportedvisibility
example that supports "private", "unlisted", "public" etc..But because microformats is pretty fluid it becomes quite complicated when there are some fields that should accept multiple values (mp-syndicate-to
), and some that should only accept single values (visibility
), and some that could be from a list but allow new values (category
).
There is already the prior art of the category query #5 and syndicate-to
that are both fairly different already.
In an ideal world there would be a way to define support for any existing property that would also work with any future or custom property too, this could potentially allow micropub clients to be future proof and display a ui for any property.
Hmmm interesting @grantcodes that’s definitely something to think through
So initially brainstorming this: you definitely don't want to simplify the syndicate-to object because that is needed. I also don't know that you would want to complicate the category array by making the strings be objects, because then you're just adding complexity turning all the category strings into an object like { uid: categoryName }
So instead, I'm wondering if there are two known value types of properties: objects and strings. A string is a simple base-line and if you need to control anything else about it other than having it be a simple string it becomes a standard object.
I think, as you said, you also need to define some behaviors around a property, so I'm roughly suggesting something like this:
properties: {
"visibility": {
"new-values": false,
"max-values": 1,
"value-type": "string",
"default": "private",
"options": [
"public",
"private",
"unlisted"
]
},
"category": {
"new-values": true,
"max-values": 0, // 0 = unlimited
"value-type": "string",
"default": null, // Or this could be undefined
"options": [
// this is an array of strings of previous categories
]
},
"syndicate-to": {
"new-values": false,
"max-values": 0,
"value-type": "object",
"default": null,
"options": [
{
"uid": "uid of object",
"name": "display name of object"
},
{
"uid": "twitter-service",
"name": "Twitter Username"
},
{
"uid": "github-service",
"name": "GitHub Username"
},
]
}
}
There are some immediate potential issues with this direction that need to be taken into consideration, but it's something we can iterate on. For certain things like categories, there can be a LOT of values, thus it may be better to instead of returning an array of values, to provide some indicator that the user has to send a different query for the given options, maybe it's by leaving out the options attribute of the property object.
In which case:
NOTE: This would alter behavior of syndicate-to values, so modern Micropub clients would first have to check if the properties object exists, if so they would use that, and if not, they would need to look in the standard location for syndicate-to values.
EDIT: Based on the conversation by @grantcodes in https://github.com/indieweb/micropub-extensions/issues/11#issuecomment-483658170, I have added a default attribute to the brainstorm above so that a client knows what value it should default to. If a property shouldn't have a default value we can either set default to null OR just not include that attribute, I'm fine either way
This GitHub issue is going to be refocused on the original two issues:
1) Hiding properties in a client that aren't supported by a server 2) Providing pre-defined options and defaults for those supported properties
The other conversations in this issue around supporting new properties, etc are moving to this new issue: https://github.com/indieweb/micropub-extensions/issues/21 which is about helping clients to add support for properties that they don't know about or don't support already
Has anyone done any server work to implement this at a basic level? @dshanske @gRegorLove @grantcodes
I'm planning on adding some basic support to my server that essentially provides something like:
properties: [
{
"name": "visibility"
"default": "private",
"options": [
"public",
"private",
"unlisted",
"protected"
]
},
{
"name": "category"
},
{
"name": "syndicate-to"
}
}
This is a simple array with objects that MUST contain a name, and the name MUST match the property name that will be included in the Micropub request. Also, you'll notice the server MAY return a default value and/or a list of options. Since category and syndicate-to's options list can be long, on my server I'm opting out of returning those and instead it has to be fetched separately using their query endpoints. I'll report back after I've implemented this both on my server and in Chronicler and let you all know how it turned out for me.
I am willing to. I only do the properties, not their values yet.
You do currently include the available properties? What does your current return look like for this Endpoint?
Properties as a single level array. But no one is consuming it
I implemented initial support in Quill for this. Quill now looks for the following object in the q=config
response:
"visibility": ["public","unlisted","private"]
The reasoning for this is I want clients to be aware of the meaning of these values, and I want servers to be able to support only a subset of these values. I also don't want servers to be able to define arbitrary visibilities here, because visibility is not the same as access control (see audience for access control).
Quill hides the syndication options if you choose "private", so it needs to know what these strings mean. I also want clients to be able to localize these strings, so that's why the server doesn't return a label for them either.
Another question with this: Should a client decide to hide UI for properties it cannot detect support for? I think previously there was a general reasoning for no because servers should support accepting property, but that feels dangerous with privacy related things like visibility.
But extrapolating on that it would be nice to be able to tell if other properties are / are not supported (micro.blog being a good example). For that I think the properties
array mentioned previously works well. If a server does not return a properties
option you can default to showing all non dangerous UI options, but if there is a properties
you can hide certain things.
I think I will try to implement something along those lines in together and my other micropub clients.
I think this is getting confused with #1.
Manton and I hashed this out a bit in Austin and shipped it on Micro.blog and Quill. Quill will only show interfaces for supported post types if the micropub endpoint says it supports only certain post types. If the micropub endpoint doesn't specify, then Quill shows everything.
Hey, I haven’t been around much because I’ve been busy, but this popped up in my GitHub notifications. I don’t think it’s confused with #1, it’s a sibling to #1. The very first post in this issue by GWG says “which experimental properties the endpoint supports so the client can choose to HIDE unsupported ones”
Yep I agree with @EdwardHinkle
There is definite overlap, but there are clear differences between post types and other properties.
In particular the properties that are more related to how posts are handled on the backend, rather than their content. visibility
& post-status
definitely being the biggest ones for now as @EdwardHinkle mentioned. If a user trys to save a post as a draft but their site doesn't support drafts that is potentially dangerous.
The solution that @aaronpk is using for visibility
is fine, but doesn't seem very extendable to me, as more similar things get added the top level of the micropub config could get very noisy.
Then there are lots of other things that may not be supported but are not necessarily dangerous - eg. mp-slug
, category
etc etc. So it would still be nice to be able so remove redundant UI components in micropub clients.
I just wanted to highlight a proposal from #1 that I think is an elegant solution to this, building off of the post-types
field. A simplified version that just includes the supported properties for a given post type would look like something like this:
GET /q=config
{
"post-types": [
{
"type": "note",
"name": "Note",
"properties": [ "content", "category", "photo", "published", "post-status" ]
}
]
}
I've settled on the following contract when calling q=properties
:
{
"properties": [
{
"name": "name",
"hints": [],
"display-name": "Title"
},
{
"name": "nickname",
"hints": [],
"display-name": "Nickname"
},
{
"name": "photo",
"hints": [
"url"
],
"display-name": "Photo"
},
{
"name": "published",
"hints": [
"date"
],
"display-name": "Date Published"
},
{
"name": "category",
"hints": [
"multivalue"
],
"display-name": "Category / tag"
},
{
"name": "rsvp",
"hints": [],
"options": [
"yes",
"no",
"maybe",
"interested"
],
"default": "yes",
"display-name": "RSVP"
},
{
"name": "content",
"hints": [
"multiline"
],
"display-name": "content"
},
{
"name": "syndication",
"hints": [
"multivalue",
"url"
],
"display-name": "Syndication URL"
},
{
"name": "summary",
"hints": [],
"display-name": "Summary"
},
{
"name": "end",
"hints": [
"date"
],
"display-name": "End Date"
},
{
"name": "start",
"hints": [
"date"
],
"display-name": "Start Date"
},
{
"name": "num",
"hints": [],
"display-name": "Number"
},
{
"name": "unit",
"hints": [],
"display-name": "Unit"
},
{
"name": "url",
"hints": [
"url"
],
"display-name": "Url"
},
{
"name": "rel=twitter",
"hints": [],
"display-name": "Twitter username"
},
{
"name": "repost-of",
"hints": [
"url"
],
"display-name": "URL to be Reposted"
},
{
"name": "like-of",
"hints": [
"url"
],
"display-name": "URL to Like"
},
{
"name": "in-reply-to",
"hints": [
"url"
],
"display-name": "URL to Reply To"
},
{
"name": "bookmark-of",
"hints": [
"url"
],
"display-name": "URL to Bookmark"
},
{
"name": "read-status",
"hints": [],
"options": [
"to-read",
"reading",
"finished"
],
"default": "finished",
"display-name": "Reading Status"
},
{
"name": "read-of",
"hints": [
"url"
],
"display-name": "URL to Mark Reading Status Of"
}
]
}
The hints
allow for making it clear to a consumer how to style the input, i.e. should it be multi-line input, should we have some way of specifying multiple items, etc.
I've also followed the idea of options
and default
, as well as being able to provide a friendly display-name
to the client.
This works really nicely in conjunction with #33.
I'm not exactly sure why there should be a separate ?q=properties
. Any such property declarations belong merged with ?q=query
and its post-types
list. (Shaving off a few bytes on the first one is a bad tradeoff for requiring more API requests.)
Also I would advocate for more blatant HTML parity when it comes to naming things:
{
"media-endpoint": "…",
"syndicate-to": […],
"post-types": [
{
"type": "note",
"name": "Blog/Technote",
"-map": "technote",
"properties": [
{
"name:" "content",
"label": "Content",
"type": "textarea markdown",
"value": "## Note\n...",
"required": true,
"-map": "stdin"
},
{
"name": "summary",
"label": "Timeline note",
"type": "text plain",
"placeholder": "commit description...",
"-map": "title"
},
{
"name": "background-color",
"type": "color",
"required": false,
"-map": "bgcolor"
},
{
"name:" "photo",
"type": "file",
"accepts": "image/*",
"is-media": true,
"required": false
}
],
"required-properties": ["content"],
"accepts-media": true
},
{
"type": "entry",
"name": "Wiki page",
"-map": "wiki",
"accepts-media": true,
"properties": [
{ "name": "content", …},
{ "name": "title", …},
{ "name": "file", …}
],
"required-properties": ["content", "title"]
}
]
}
It's unlikely a compound properties list would do you any good. Your micropub endpoint either has but one h-type supported; so it doesn't add much duplication when properties are noted right there. And if different post-types were supported, the overlap would be mostly just the content field. But even that is possible to divert between post-types (e.g. "h-entry" being a blog post, but "h-chat" required a single-line content field).
Changed properties:
to be a list of dicts (rather than having each key be the name:), as that's more in line with the existing config structures. Now this opens up the possibility of duplicate entries. (But optimizing for edge cases is rarely a good idea.)
Another diversion from the post-types
structure would be label:
or title:
instead of name:
for the properties list.
Instead of a hint:
list (as proposed by @jamietanna above), it might be more consistent to use type:
(like in <input type=…>
). Which implies a lot of known vocabulary:
type | what it renders as |
---|---|
text |
standard <input> field |
textarea |
a multiline <textarea> content field |
select |
a <select> box, taking values from a select: [] list |
url |
standard input field, but with url validation |
email |
standard input field, but with email validation |
datetime |
calendar input |
file |
an upload element |
hidden |
secret input field |
checkbox |
boolean property (for e.g. visibility?) |
h-card |
nested structure |
Speaking of select
, that might be controversial. Noone can ever settle between select/choices/options. But again for strong parity, I would also prefer "select": []
to enlist the allowed values.
{
"name": "tkt-type",
"type": "select",
"select": ["Code_Defect", "Documentation", "Feature_Request"]
}
And once you go with the input field scheme, you also get obvious attributes like placeholder:
and value:
(rather than default:
) here.
attr | pretty much what it means in HTML |
---|---|
name: |
property field name |
required: |
isn't optional (bool-ish attr) |
value: |
the preset/default value |
placeholder: |
example value |
select: |
a <select> box, taking values from a select: [] list |
label: |
or title: ? |
multiple: |
for select property (bool-ish attr) |
accepts: |
mime list for file upload properties |
-map: |
internal attribute (mp client should ignore those) |
Arguably this might be a bit too programmatic - it's essentially a JSON serialization of form fields. But then again, certainly helps auto-discovery, or merging standard and unknown properties/post-types, or even super dumb clients (craft a <form>
pointed directly at the MP endpoint).
reg extensions:
[ "post-types-properties-dict-input" ]
This is getting quite complicated. I think this is out of scope for Micropub. Very few people need to build a general-purpose editor that can dynamically adapt to this level.
My suggestion above (July 15th) would solve the original request in an easy, backwards-compatible way, though.
There are per-post-type properties, and global properties. I had only intended to address global properties. Proposing that: visibility, post-status, and mp-slug all apply equally to all post types, so should be specified as such. I think the proposals about per-post type items are worth discussion,
Quill and Indiebookclub as clients now implement visibility as a return in q=config.
indiebookclub now checks for the same config options Aaron described above.
Separated from #1.
Suggest that the config query return a properties element that notes which experimental properties the endpoint supports so the client can choose to hide unsupported ones