webmention.io icon indicating copy to clipboard operation
webmention.io copied to clipboard

Parsing different types of webmention on the same source page

Open rowanmanning opened this issue 4 years ago • 1 comments

Hi, I'm trying to publish webmentions from my own site and I'm running into an issue which may be more with XRay, or it may be my misunderstanding of how webmentions should work. Happy to move this if the former and be schooled if the latter!

I want to be able to write a post which sends different webmention types to different pages. So, for example: I might want to reference https://example.com/1 and for that to be a like-of, and on the same page reference https://example.com/2 and that be an in-reply-to. However when I send a webmention for a page with multiple links, only the first type is used.

What I'm hoping to achieve

Given this HTML:

<div class="h-entry">
    <div class="p-author h-card">
        <span class="p-name">Testy McTestface</span>
    </div>
    <a href="http://mysite.com/" class="u-url">The current URL</a>
    <div class="e-content">

        <a href="https://example.com/1" class="u-like-of">
            I like this post
        </a>

        <a href="https://example.com/2" class="u-in-reply-to">
            I agree with this
        </a>

    </div>
</div>

I would like two webmentions to be picked up from this page:

  1. A u-like-of of example.com/1 with the content I like this post
  2. A u-in-reply-to of example.com/2 with the content I agree with this

What I've tried so far

My main assumption is that I'm just bad at understanding how microformats work, I tracked the way webmention.io parses a page to XRay and have been using https://xray.p3k.app/ to parse some examples.

The initial HTML

The HTML from above
<div class="h-entry">
    <div class="p-author h-card">
        <span class="p-name">Testy McTestface</span>
    </div>
    <a href="http://mysite.com/" class="u-url">The current URL</a>
    <div class="e-content">

        <a href="https://example.com/1" class="u-like-of">
            I like this post
        </a>

        <a href="https://example.com/2" class="u-in-reply-to">
            I agree with this
        </a>

    </div>
</div>

Responds with:

XRay JSON output
{
    "data": {
        "type": "entry",
        "url": "http://mysite.com/",
        "in-reply-to": [
            "https://example.com/2"
        ],
        "like-of": [
            "https://example.com/1"
        ],
        "content": {
            "text": "I like this post\n        \n\n        \n            I agree with this",
            "html": "<a href=\"https://example.com/1\" class=\"u-like-of\">\n            I like this post\n        </a>\n\n        <a href=\"https://example.com/2\" class=\"u-in-reply-to\">\n            I agree with this\n        </a>"
        },
        "author": {
            "type": "card",
            "name": "Testy McTestface",
            "url": false,
            "photo": null
        },
        "post-type": "like"
    },
    "url": "http://mysite.com/",
    "code": null,
    "source-format": "mf2+html"
}

The data.post-type property being set to like means that the webmention for example.com/2 is still a like-of rather than an in-reply-to. Also the full content of the page is used rather than the content of the link.

Nested h-entries

So I tried nesting h-entries, so that each could use a different type (showing only e-content to keep this brief):

...
<span class="h-entry">
    <a href="https://example.com/1" class="u-url u-like-of e-content">
        I like this post
    </a>
</span>

<span class="h-entry">
    <a href="https://example.com/2" class="u-url u-in-reply-to e-content">
        I agree with this
    </a>
</span>
...

Responds with:

XRay JSON output
{
    "data": {
        "type": "entry",
        "url": "http://mysite.com/",
        "content": {
            "text": "I like this post\n\t\t\t\n\t\t\n\n\t\t\n\t\t\t\n\t\t\t\tI agree with this",
            "html": "<span class=\"h-entry\">\n\t\t\t<a href=\"https://example.com/1\" class=\"u-url u-like-of e-content\">\n\t\t\t\tI like this post\n\t\t\t</a>\n\t\t</span>\n\n\t\t<span class=\"h-entry\">\n\t\t\t<a href=\"https://example.com/2\" class=\"u-url u-in-reply-to e-content\">\n\t\t\t\tI agree with this\n\t\t\t</a>\n\t\t</span>"
        },
        "author": {
            "type": "card",
            "name": "Testy McTestface",
            "url": false,
            "photo": null
        },
        "post-type": "note"
    },
    "url": "",
    "code": null,
    "source-format": "mf2+html"
}

This feels like a step back because nested h-entries aren't found, and the main post-type is now note. The webmention for this still contains the full page content.

Using h-cite

So I tried using h-cite, which doesn't feel 100% right, but thought it was worth checking:

...
<a href="https://example.com/1" class="h-cite u-like-of">
    I like this post
</a>

<a href="https://example.com/2" class="h-cite u-in-reply-to">
    I agree with this
</a>
...

Responds with:

XRay JSON output
{
    "data": {
        "type": "entry",
        "url": "http://mysite.com/",
        "in-reply-to": [
            "https://example.com/2"
        ],
        "like-of": [
            "https://example.com/1"
        ],
        "content": {
            "text": "I like this post\n        \n        \n        \n            I agree with this",
            "html": "<a href=\"https://example.com/1\" class=\"h-cite u-like-of\">\n            I like this post\n        </a>\n        \n        <a href=\"https://example.com/2\" class=\"h-cite u-in-reply-to\">\n            I agree with this\n        </a>"
        },
        "author": {
            "type": "card",
            "name": "Testy McTestface",
            "url": false,
            "photo": null
        },
        "post-type": "like",
        "refs": {
            "https://example.com/2": {
                "type": "entry",
                "url": "https://example.com/2",
                "name": "I agree with this",
                "post-type": "article"
            },
            "https://example.com/1": {
                "type": "entry",
                "url": "https://example.com/1",
                "name": "I like this post",
                "post-type": "article"
            }
        }
    },
    "url": "http://mysite.com/",
    "code": null,
    "source-format": "mf2+html"
}

This feels a little closer, because the cites appear as refs, however the top h-entry post-type is like and so all webmentions are considered like-of. Also the full page content is still used in each mention


Do you know if this is possible? Am I misunderstanding how webmentions should work, and should I be thinking about each reply or like having a separate URL (which is what I've mostly seen people doing)? Thanks for your time :)

rowanmanning avatar Jun 13 '21 09:06 rowanmanning

Some additional context of where I got the idea that I'd like to do this, and just assumed that it'd work, is by validating my microformats on https://pin13.net/mf2/ - I (possibly wrongly) assumed that child elements would get picked up, for example the following markup:

<div class="h-entry">
	<div class="p-author h-card">
		<span class="p-name">Testy McTestface</span>
	</div>
	<a href="http://mysite.com/" class="u-url">The current URL</a>
	<div class="e-content">

		<span class="h-card">
			<a href="https://example.com/1" class="u-like-of e-content">
				I like this post
			</a>
		</span>
		
		<span class="h-card">
			<a href="https://example.com/2" class="u-in-reply-to e-content">
				I agree with this
			</a>
		</span>

	</div>
</div>

When it's run through the parser linked above, will include children:

...
"children": [
    {
        "type": [
            "h-card"
        ],
        "properties": {
            "like-of": [
                "https://example.com/1"
            ],
            "content": [
                {
                    "html": "I like this post",
                    "value": "I like this post"
                }
            ]
        }
    },
    {
        "type": [
            "h-card"
        ],
        "properties": {
            "in-reply-to": [
                "https://example.com/2"
            ],
            "content": [
                {
                    "html": "I agree with this",
                    "value": "I agree with this"
                }
            ]
        }
    }
]
...
Full JSON output
{
    "items": [
        {
            "type": [
                "h-entry"
            ],
            "properties": {
                "url": [
                    "http://mysite.com/"
                ],
                "content": [
                    {
                        "html": "<span class=\"h-card\">\n\t\t\t<a href=\"https://example.com/1\" class=\"u-like-of e-content\">\n\t\t\t\tI like this post\n\t\t\t</a>\n\t\t</span>\n\t\t\n\t\t<span class=\"h-card\">\n\t\t\t<a href=\"https://example.com/2\" class=\"u-in-reply-to e-content\">\n\t\t\t\tI agree with this\n\t\t\t</a>\n\t\t</span>",
                        "value": "I like this post I agree with this"
                    }
                ],
                "author": [
                    {
                        "type": [
                            "h-card"
                        ],
                        "properties": {
                            "name": [
                                "Testy McTestface"
                            ]
                        },
                        "value": "Testy McTestface"
                    }
                ]
            },
            "children": [
                {
                    "type": [
                        "h-card"
                    ],
                    "properties": {
                        "like-of": [
                            "https://example.com/1"
                        ],
                        "content": [
                            {
                                "html": "I like this post",
                                "value": "I like this post"
                            }
                        ]
                    }
                },
                {
                    "type": [
                        "h-card"
                    ],
                    "properties": {
                        "in-reply-to": [
                            "https://example.com/2"
                        ],
                        "content": [
                            {
                                "html": "I agree with this",
                                "value": "I agree with this"
                            }
                        ]
                    }
                }
            ]
        }
    ],
    "rels": {},
    "rel-urls": {},
    "debug": {
        "package": "https://packagist.org/packages/mf2/mf2",
        "source": "https://github.com/indieweb/php-mf2",
        "version": "0.4.6",
        "note": [
            "This output was generated from the php-mf2 library available at https://github.com/indieweb/php-mf2",
            "Please file any issues with the parser at https://github.com/indieweb/php-mf2/issues",
            "Using the Masterminds HTML5 parser"
        ]
    }
}

rowanmanning avatar Jun 13 '21 15:06 rowanmanning

This sounds like two problems. One, you're stretching the limits of what most people are going to be expecting when receiving a webmention. The other is a misunderstanding of how the content of a post is parsed.

In this example:

        <a href="https://example.com/1" class="u-like-of">
            I like this post
        </a>

        <a href="https://example.com/2" class="u-in-reply-to">
            I agree with this
        </a>

The "I like this post" and "I agree with this" text have nothing to do with the u-like-of and u-in-reply-to properties. That full text is correctly being parsed as the content of the post.

Theoretically it is possible to create a single post that is a u-like-of a example.com post and u-in-reply-to an example.org post, but in practice that is not common and I doubt most people would be handling it like you expect.

My advice is to not try to be so clever, and stick to simpler publishing formats where one post corresponds to one action from you.

aaronpk avatar Aug 19 '23 19:08 aaronpk