indieweb / micropub-extensions

Issue tracking for Micropub extensions
https://indieweb.org/Micropub-extensions
10 stars 0 forks source link

Query for Supported Properties #8

Open dshanske opened 5 years ago

dshanske commented 5 years ago

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

EdwardHinkle commented 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.

gRegorLove commented 5 years ago

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.

grantcodes commented 5 years ago

So I think there are at least 2 ways we would need to show full support for a property:

  1. The basic property is supported and accepts any value, e.g. things like summary and category can accept pretty much anything, but would be nice to know if they are supported
  2. A property that accepts a value from a set list of values, eg the visibility 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.

EdwardHinkle commented 5 years ago

Hmmm interesting @grantcodes that’s definitely something to think through

EdwardHinkle commented 5 years ago

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

EdwardHinkle commented 5 years ago

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

EdwardHinkle commented 5 years ago

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.

dshanske commented 5 years ago

I am willing to. I only do the properties, not their values yet.

EdwardHinkle commented 5 years ago

You do currently include the available properties? What does your current return look like for this Endpoint?

dshanske commented 5 years ago

Properties as a single level array. But no one is consuming it

aaronpk commented 4 years ago

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.

grantcodes commented 4 years ago

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.

aaronpk commented 4 years ago

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.

EdwardHinkle commented 4 years ago

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”

1 is strictly about properties that can be defined as post type. It doesn’t solve the very real issue of drafts status, visibility, etc.

grantcodes commented 4 years ago

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.

manton commented 4 years ago

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" ]
    }
  ]
}
jamietanna commented 3 years ago

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.

prof-milki commented 3 years ago

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"]
        }
    ]
}
Rationale

reg extensions: [ "post-types-properties-dict-input" ]

manton commented 3 years ago

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.

dshanske commented 2 years ago

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.

gRegorLove commented 2 years ago

indiebookclub now checks for the same config options Aaron described above.