├── .gitignore ├── CNAME ├── README.md ├── jf2-context.jsonld ├── publish ├── 2016-07-28-FPWD │ └── index-src.html ├── 2017-06-12-WD │ └── index-src.html └── 2017-06-27-WD │ └── index-src.html └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | jf2.spec.indieweb.org -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JF2 Editor's Draft 2 | Simplified JSON format of post streams 3 | 4 | Contributions to this specification are governed by the W3C IPR Policy. Pull requests will be accepted only if the submitter was a member of the W3C Social WG but issues can be opened by anyone. 5 | -------------------------------------------------------------------------------- /jf2-context.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "http://www.w3.org/TR/activitystreams-core/activitystreams2-context", 4 | { 5 | "mf": "http://microformats.org/wiki/", 6 | "vcard": "http://www.w3.org/2006/vcard/ns#", 7 | "jf2": "https://github.com/w3c-social/Social-Syntax-Brainstorming/wiki/jf2#", 8 | "iwc": "http://indiewebcamp.com/", 9 | 10 | "Adr": "mf:h-adr", 11 | "Card": "mf:h-card", 12 | "Entry": "mf:h-entry", 13 | "Feed": "mf:h-feed", 14 | "Item": "mf:h-item", 15 | "Listing": "mf:h-listing", 16 | "Product": "mf:h-product", 17 | "Recipe": "mf:h-recipe", 18 | "Resume": "mf:h-resume", 19 | "Review": "mf:h-review", 20 | "Review-aggregate": "mf:h-review-aggregate", 21 | "Cite": "mf:h-cite", 22 | 23 | "additional-name": "vcard:additional-name", 24 | "adr": "vcard:adr", 25 | "anniversary": "vcard:anniversary", 26 | "bday": "vcard:bday", 27 | "category": "vcard:category", 28 | "country-name": "vcard:country-name", 29 | "email": "vcard:hasEmail", 30 | "family-name": "vcard:family-name", 31 | "given-name": "vcard:given-name", 32 | "honorific-prefix": "vcard:honorific-prefix", 33 | "honorific-suffix": "vcard:honorific-suffix", 34 | "impp": "vcard:hasInstantMessage", 35 | "nickname": "vcard:nickname", 36 | "org": "vcard:organization-name", 37 | "organization-unit": "vcard:organizational-unit", 38 | "postal-code": "vcard:hasPostalCode", 39 | "street-address": "vcard:street-address", 40 | "locality": "vcard:locality", 41 | "region": "vcard:region", 42 | "tel": "vcard:hasTelephone", 43 | "tz": "vcard:tz", 44 | "uid": "vcard:hasUID", 45 | "fn": "vcard:fn", 46 | 47 | "affiliation": "mf:microformats2#p-affiliation", 48 | "audio": "mf:microformats2#u-audio", 49 | "best": "mf:microformats2#p-best", 50 | "brand": "mf:microformats2#p-brand", 51 | "contact": "mf:microformats2#p-contact", 52 | "count": "mf:microformats2#p-count", 53 | "education": "mf:microformats2#p-education", 54 | "experience": "mf:microformats2#p-experience", 55 | "extended-address": "mf:microformats2#p-extended-address", 56 | "gender-identity": "mf:microformats2#p-gender-identity", 57 | "identifier": "mf:microformats2#u-identifier", 58 | "ingredient": "mf:microformats2#p-ingredient", 59 | "instructions": "mf:microformats2#e-instructions", 60 | "job-title": "mf:microformats2#p-job-title", 61 | "key": "mf:microformats2#u-key", 62 | "label": "mf:microformats2#p-label", 63 | "note": "mf:microformats2#p-note", 64 | "nutrition": "mf:microformats2#p-nutrition", 65 | "post-office-box": "mf:microformats2#p-post-office-box", 66 | "price": "mf:microformats2#p-price", 67 | "rating": "mf:microformats2#p-rating", 68 | "rev": "mf:microformats2#dt-rev", 69 | "review": "mf:microformats2#p-review", 70 | "reviewed": "mf:microformats2#dt-reviewed", 71 | "reviewer": "mf:microformats2#p-reviewer", 72 | "role": "mf:microformats2#p-role", 73 | "skill": "mf:microformats2#p-skill", 74 | "sort-string": "mf:microformats2#p-sort-string", 75 | "video": "mf:microformats2#u-video", 76 | "votes": "mf:microformats2#p-votes", 77 | "worst": "mf:microformats2#p-worst", 78 | "yield": "mf:microformats2#p-yield", 79 | "publication": "mf:h-cite#publication", 80 | "accessed": "mf:h-cite#dt-accessed", 81 | "syndication": "mf:rel-syndication", 82 | "shortlink": "mf:rel-shortlink", 83 | "rsvp": "mf:rsvp", 84 | "sex": "mf:h-card#p-sex", 85 | "gender": "mf:h-card#p-gender-identity", 86 | 87 | "mf2ex": "mf:microformats2-experimental-properties#", 88 | "x-dietary-preference": "mf2ex:p-x-dietary-preference", 89 | "x-pronoun-nominative": "mf2ex:p-x-pronoun-nominative", 90 | "x-pronoun-oblique": "mf2ex:p-x-pronoun-oblique", 91 | "x-pronoun-possessive": "mf2ex:p-x-pronoun-posessive", 92 | "x-sexual-preference": "mf2ex:p-x-sexual-preference", 93 | "x-username": "mf2ex:h-x-username", 94 | 95 | "comment": "iwc:comments", 96 | "like-of": "iwc:like", 97 | "repost-of": "iwc:repost", 98 | "invitee": "iwc:invite" 99 | } 100 | ] 101 | } 102 | -------------------------------------------------------------------------------- /publish/2016-07-28-FPWD/index-src.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |78 | This document describes a JSON serialization format to describe simple 79 | streams of data as well as single objects of data for data transfer and 80 | processing. 81 |
82 |105 | JF2 is a JSON based document format that describes lists and single entries 106 | of information. The primary use case for JF2 is to create a JSON format for 107 | social web post objects to be processed directly by client software and by other 108 | servers. 109 |
110 |111 | The name JF2 comes from its origins in being a direct parsed format of 112 | Microformats-2 (MF2) data from html. Rather than defining a new vocabulary, 113 | JF2 uses the vocabulary defined by [[microformats2]] 114 | however any other suitable vocabulary. 115 |
116 |117 | It is relevant to note that JF2 objects have been most useful as programming objects, not 118 | as a serialization format. This document using javascript object notation for serializing 119 | to explain structure, but any language will have its own native structure in which JF2 would 120 | be stored. 121 |
122 |127 | JF2 has evolved as a result of a variety of use-cases for different implementations 128 | exploring ways to simplify their existing use of canonical parsed microformats2 JSON 129 | output. All of these use cases in particular are simply to have a single format for 130 | the storage and use of social web objects. 131 |
132 |133 | Webmention.io is a service that provides webmention 134 | processing and verification on behalf of other sites. It uses a simple JSON object to 135 | transfer a processed webmention back to the client site's javascript for display. The 136 | attributes are intended to be processed only by the client site's javascript code, not 137 | by anything else. 138 |
139 |140 | mf2util is a utility library that provides a layer on top 141 | of microformats processing. The library returns only a simple JSON object and strips 142 | off any unnecessary information leaving the library user only the most essential information. 143 |
144 |145 | Various services (xray, unmung, socialstreams) 146 | provide conversion from microformats pages in to JF2 for quick inspection to 147 | validate proper semantics. 148 |
149 |154 | JF2 consists of JSON objects which are defined by a type property that will specify 155 | the vocabulary of the object. Properties are attached to these objects which will contain 156 | either a single string, a single object, an array of strings, or an array of objects. 157 | Arrays that have only a single item SHOULD be condensed into only the single containing item. 158 | Any property of an object MAY be a single item or an array of items except for reserved words 159 | defined below. 160 |
161 |164 | The following keywords are reserved and cannot be used as property names in vocabularies. 165 |
166 |203 | A post is composed of a "type" property, and one or more additional properties that describe the post. 204 |
205 |206 | The "type" property has a value that describes the vocabulary of this post. Common values include "entry", "card", etc. See Microformats 2 vocabularies for the full list when using a microformats based vocabulary. 207 |
208 |209 | Any additional properties in the post object are considered part of the post's vocabulary. 210 |
211 | 212 |216 | The list of valid post properties is defined by the vocabularies. This allows new vocabularies to be developed outside the development of the syntax. 217 |
218 |219 | Most values will be strings. If a property (such as `author` for example) references another 220 | object, it may be serialized in two ways: as an object serialized as the property value or as 221 | the unique identifier or URL where the object can be found. See Using References 222 |
223 |224 | Values may also be arrays if the vocabulary allows for multiple values of the property. 225 |
226 | 227 |
232 | {
233 | "type": "entry",
234 | "published": "2015-10-20T15:49:00-0700",
235 | "url": "http://example.com/post/fsjeuu8372",
236 | "author": {
237 | "type": "card",
238 | "name": "Alice",
239 | "url": "http://alice.example.com",
240 | "photo": "http://alice.example.com/photo.jpg"
241 | },
242 | "name": "Hello World",
243 | "content": "This is a blog post",
244 | "category": "Posts"
245 | }
246 |
247 |
248 |
249 | {
250 | "type": "entry",
251 | "published": "2015-10-20T15:49:00-0700",
252 | "url": "http://example.com/like/r23eugi02c",
253 | "author": {
254 | "type": "card",
255 | "name": "Alice",
256 | "url": "http://alice.example.com",
257 | "photo": "http://alice.example.com/photo.jpg"
258 | },
259 | "like-of": "http://bob.example.com/post/100",
260 | "category": ["Likes", "Posts"]
261 | }
262 |
263 | 285 | By default, any string value should be interpreted as literal plaintext. This means when displaying a string in an HTML page, it must be HTML escaped. 286 |
287 | 288 |289 | If the value of a property is to be interpreted as HTML, it MUST be enclosed in an object noting its content-type as follows. 290 |
291 | 292 |
293 | {
294 | "type": "entry",
295 | "content": {
296 | "content-type": "text/html",
297 | "value": "<b>Hello World</b>"
298 | }
299 | }
300 |
301 |
302 | 305 | Since HTML video/audio/picture tags may have multiple URLs, we need a way to convey this information in the JSON representation. 306 |
307 | 308 |309 | <div class="h-entry"> 310 | <video class="u-video" width="640" height="360" preload controls> 311 | <source src="sample_h264.mov" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' /> 312 | <source src="sample_ogg.ogv" type='video/ogg; codecs="theora, vorbis"' /> 313 | <source src="sample_webm.webm" type='video/webm; codecs="vp8, vorbis"' /> 314 | </video> 315 | </div> 316 |317 | 318 |
319 | {
320 | "type": "entry",
321 | "video": [
322 | {
323 | "content-type": "video/mp4",
324 | "url": "sample_h264.mov"
325 | },
326 | {
327 | "content-type": "video/ogg",
328 | "url": "sample_ogg.ogg"
329 | },
330 | {
331 | "content-type": "video/webm",
332 | "url": "sample_webm.webm"
333 | }
334 | ]
335 | }
336 |
337 |
338 | 345 | The purpose of the `references` property is to exclude any non-authoritative 346 | data from the defined object. To do this, non-authoritative data is moved so 347 | that implementations looking to process only authoritative data may simply ignore 348 | the references property and fetch any data that would be contained there from its 349 | authoritative source. 350 |
351 |352 | If a property is a reference to an object that is defined authoritatively in 353 | some other location, the `references` property SHOULD be used. The property 354 | SHOULD contain only the unique identifier or URL where the authoritative data 355 | may be found. In the references object, the URL or unique identifier MAY 356 | be entered as the key field and a serialization of the referenced object MAY 357 | be provided. This serialization of the referenced object MAY be incomplete 358 | so as to provide only necessary data. 359 |
360 |361 | Parsing implementations SHOULD fetch data from the authoritative source instead of using 362 | the references object. 363 |
364 |
367 | {
368 | "type": "entry",
369 | "published": "2015-10-20T15:49:00-0700",
370 | "url": "http://example.com/post/fsjeuu8372",
371 | "author": "http://alice.example.com",
372 | "name": "Hello World",
373 | "content": "This is a blog post",
374 | "category": "Posts",
375 | "references": {
376 | "http://alice.example.com": {
377 | "type": "card",
378 | "name": "Alice",
379 | "url": "http://alice.example.com",
380 | "photo": "http://alice.example.com/photo.jpg"
381 | }
382 | }
383 | }
384 |
385 |
386 |
387 | {
388 | "type": "entry",
389 | "published": "2015-10-20T15:49:00-0700",
390 | "url": "http://example.com/like/r23eugi02c",
391 | "author": {
392 | "type": "card",
393 | "name": "Alice",
394 | "url": "http://alice.example.com",
395 | "photo": "http://alice.example.com/photo.jpg"
396 | },
397 | "like-of": "http://bob.example.com/post/100",
398 | "category": ["Likes", "Posts"],
399 | "references": {
400 | "http://bob.example.com/post/100": {
401 | "type": "entry",
402 | "published": "2015-10-18T12:33:00-0700",
403 | "url": "http://bob.example.com/post/100",
404 | "author": "http://bob.example.com",
405 | "name": "My First Post",
406 | "content": "This is my first post on my new blog, I hope you like it"
407 | },
408 | "http://bob.example.com": {
409 | "type": "card",
410 | "name": "Bob",
411 | "url": "http://bob.example.com",
412 | "photo": "http://bob.example.com/mypicture.jpg"
413 | }
414 | }
415 | }
416 |
417 | 424 | Posts can live inside of collections. A collection may be a home page feed, or a feed of other posts such as a list of contacts, a list of things someone has liked, etc. There is no requirement that all posts in a collection need to be of the same type. 425 |
426 | 427 |428 | The collection may also have its own properties such as "name" or "author". 429 |
430 | 431 |
432 | {
433 | "type": "feed",
434 | "url": "http://alice.example.com/collectionurl",
435 | "name": "Alice's Home Page",
436 | "author": {
437 | "type": "card",
438 | "name": "Alice",
439 | "url": "http://alice.example.com",
440 | "photo": "http://alice.example.com/photo"
441 | },
442 | "children": [
443 | { ... },
444 | { ... }
445 | ]
446 | }
447 |
448 |
449 | 452 | If an HTML page contains multiple top-level items, (most commonly found when a page contains a list of [[h-entry]] objects), the parser creates an implicit top-level collection with no properties. 453 |
454 | 455 |
456 | {
457 | "children": [
458 | { ... },
459 | { ... }
460 | ]
461 | }
462 |
463 |
464 | 470 | This syntax is derived from HTML with Microformats-2, converted to JSON [[microformats2-parsing]] converted to a simplified JSON. The examples below illustrate the process. 471 |
472 | 473 |478 | <article class="h-entry"> 479 | <h1 class="p-name">Hello World</h1> 480 | <p>Published by <a class="p-author h-card" href="http://example.com/">A. Developer</a> 481 | on <a href="http://example.com/2015/10/21" class="u-url"><time class="dt-published" datetime="2015-10-21T12:00:00-0700">October 21<sup>st</sup>, 2015</time></a> 482 | 483 | <p class="p-summary">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar.</p> 484 | 485 | <div class="e-content"><p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p></div> 486 | </article> 487 |488 | 489 |
492 | {
493 | "items": [
494 | {
495 | "type": [
496 | "h-entry"
497 | ],
498 | "properties": {
499 | "author": [
500 | {
501 | "type": [
502 | "h-card"
503 | ],
504 | "properties": {
505 | "name": [
506 | "A. Developer"
507 | ],
508 | "url": [
509 | "http:\/\/example.com\/"
510 | ]
511 | },
512 | "value": "A. Developer"
513 | }
514 | ],
515 | "name": [
516 | "Hello World"
517 | ],
518 | "summary": [
519 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar."
520 | ],
521 | "url": [
522 | "http:\/\/example.com\/2015\/10\/21"
523 | ],
524 | "published": [
525 | "2015-10-21T12:00:00-0700"
526 | ],
527 | "content": [
528 | {
529 | "html": "<p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p>",
530 | "value": "Donec dapibus enim lacus, a vehicula magna bibendum non. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in."
531 | }
532 | ]
533 | }
534 | }
535 | ]
536 | }
537 |
538 |
539 |
542 | {
543 | "type": "entry",
544 | "author": {
545 | "type": "card",
546 | "url": "http://example.com",
547 | "name": "A. Developer"
548 | },
549 | "url": "http://example.com/2015/10/21",
550 | "published": "2015-10-21T12:00:00-0700",
551 | "name": "Hello World",
552 | "summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar.",
553 | "content": {
554 | "value": "<p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p>",
555 | "content-type": "text/html"
556 | }
557 | }
558 |
559 |
560 |
561 | 565 | JF2 documents all have an implicit @context field which is optional. This @context can be found at 566 | http://www.w3.org/ns/jf2 567 | and is provided only to make conversion to [[JSON-LD]] format possible. Most JF2 will process 568 | fine in JSON-LD systems, however, this support is not guaranteed and those wishing to 569 | use JF2 in JSON-LD may need to modify serialization slightly. 570 |
571 |576 | The following is a list of currently known implementations of JF2-like formats and their current differences to this document 577 |
578 | 579 |582 | Webmention.io is a hosted service for handling webmentions. 583 | Webmentions are accessed from an API that that returns a set of objects in JSON format similar to JF2. 584 | The key difference is the inclusion of some additional data wrapping the objects 585 | (source, verified, verified_data, etc) and all wrapped in a "links" array. 586 | Code available at https://github.com/aaronpk/webmention.io 587 |
588 |593 | X-Ray is a tool to return structured data from any URL. 594 | Code available at https://github.com/aaronpk/XRay 595 |
596 |601 | Unmung is a tool for converting various formats. 602 | Code available at https://github.com/kevinmarks/unmung 603 |
604 |618 | Mf2util is a utility library for interpreting microformats2. 619 | Code available at https://github.com/kylewm/mf2util 620 |
621 |629 | The authors wish to thank the Microformats, IndieWebCamp, Pump.io, and Activity Streams communities for their continued work 630 | in building the social web and helping define standards such as this one. This includes, but is certainly not limited to, 631 | Aaron Parecki, 632 | Benjamin Goering, 633 | Christopher Webber, 634 | Dave Wilkinson II, 635 | James Snell, 636 | Kyle Mahan, 637 | and 638 | Tantek Çelik. 639 |
640 |101 | This document describes a JSON serialization format to describe simple 102 | streams of data as well as single objects of data for data transfer and 103 | processing. 104 |
105 |122 | JF2 is a JSON based document format that describes lists and single entries 123 | of information. The primary use case for JF2 is to create a JSON format for 124 | social web post objects to be processed directly by client software and by other 125 | servers. 126 |
127 |128 | The name JF2 comes from its origins in being a direct parsed format of 129 | Microformats-2 (MF2) data from html. Rather than defining a new vocabulary, 130 | JF2 uses the vocabulary defined by [[microformats2]] 131 | however any other suitable vocabulary could be used. JF2 is vocabulary 132 | independent except for its profiles which are fully vocabulary aware. 133 |
134 |139 | JF2 has evolved as a result of a variety of use-cases for different implementations 140 | exploring ways to simplify their existing use of canonical parsed microformats2 JSON 141 | output. All of these use cases in particular are simply to have a single format for 142 | the storage and use of social web objects. 143 |
144 |145 | Webmention.io is a service that provides webmention 146 | processing and verification on behalf of other sites. It uses a simple JSON object to 147 | transfer a processed webmention back to the client site's javascript for display. The 148 | attributes are intended to be processed only by the client site's javascript code, not 149 | by anything else. 150 |
151 |152 | mf2util is a utility library that provides a layer on top 153 | of microformats processing. The library returns only a simple JSON object and strips 154 | off any unnecessary information leaving the library user only the most essential information. 155 |
156 |157 | Various services (xray, unmung, socialstreams) 158 | provide conversion from microformats pages in to JF2 for quick inspection to 159 | validate proper semantics. 160 |
161 |166 | JF2 consists of JSON objects which are defined by a type property that will specify 167 | the vocabulary of the object. Properties are attached to these objects which will contain 168 | either a single string, a single object, an array of strings, or an array of objects. 169 | Arrays that have only a single item SHOULD be condensed into only the single containing item. 170 | Any property of an object MAY be a single item or an array of items except for reserved words 171 | defined below. 172 |
173 |176 | The following keywords are reserved and cannot be used as property names in vocabularies. 177 |
178 |219 | A post is composed of a "type" property, and one or more additional properties that describe the post. 220 |
221 |222 | The "type" property has a value that describes the vocabulary of this post. Common values include "entry", "card", etc. See Microformats 2 vocabularies for the full list when using a microformats based vocabulary. 223 |
224 |225 | Any additional properties in the post object are considered part of the post's vocabulary. 226 |
227 | 228 |232 | The list of valid post properties is defined by the vocabularies. This allows new vocabularies to be developed outside the development of the syntax. 233 |
234 |235 | Most values will be strings. If a property (such as `author` for example) references another 236 | object, it may be serialized in two ways: as an object serialized as the property value or as 237 | the unique identifier or URL where the object can be found. See Using References 238 |
239 |240 | Values may also be arrays if the vocabulary allows for multiple values of the property. 241 |
242 | 243 |
248 | {
249 | "type": "entry",
250 | "published": "2015-10-20T15:49:00-0700",
251 | "url": "http://example.com/post/fsjeuu8372",
252 | "author": {
253 | "type": "card",
254 | "name": "Alice",
255 | "url": "http://alice.example.com",
256 | "photo": "http://alice.example.com/photo.jpg"
257 | },
258 | "name": "Hello World",
259 | "content": "This is a blog post",
260 | "category": "Posts"
261 | }
262 |
263 |
264 |
265 | {
266 | "type": "entry",
267 | "published": "2015-10-20T15:49:00-0700",
268 | "url": "http://example.com/like/r23eugi02c",
269 | "author": {
270 | "type": "card",
271 | "name": "Alice",
272 | "url": "http://alice.example.com",
273 | "photo": "http://alice.example.com/photo.jpg"
274 | },
275 | "like-of": "http://bob.example.com/post/100",
276 | "category": ["Likes", "Posts"]
277 | }
278 |
279 | 301 | By default, any string value should be interpreted as literal plaintext. 302 | This means when displaying a string in an HTML page, it must be HTML escaped. 303 |
304 | 305 |306 | If the value of a property is to be interpreted as HTML, it MUST be enclosed in 307 | an object and placed under the "html" property as follows. If a plaintext version 308 | is also available, that is placed under the "text" property. 309 |
310 | 311 |
312 | {
313 | "type": "entry",
314 | "content": {
315 | "html": "<p>Hello World</p>"
316 | "text": "Hello World"
317 | }
318 | }
319 |
320 |
321 | 324 | Since HTML video/audio/picture tags may have multiple URLs, we need a way to convey this information in the JSON representation. 325 |
326 | 327 |328 | <div class="h-entry"> 329 | <video class="u-video" width="640" height="360" preload controls> 330 | <source src="sample_h264.mov" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' /> 331 | <source src="sample_ogg.ogv" type='video/ogg; codecs="theora, vorbis"' /> 332 | <source src="sample_webm.webm" type='video/webm; codecs="vp8, vorbis"' /> 333 | </video> 334 | </div> 335 |336 | 337 |
338 | {
339 | "type": "entry",
340 | "video": [
341 | {
342 | "content-type": "video/mp4",
343 | "url": "sample_h264.mov"
344 | },
345 | {
346 | "content-type": "video/ogg",
347 | "url": "sample_ogg.ogg"
348 | },
349 | {
350 | "content-type": "video/webm",
351 | "url": "sample_webm.webm"
352 | }
353 | ]
354 | }
355 |
356 |
357 | 364 | The purpose of the `references` property is to exclude any non-authoritative 365 | data from the defined object. To do this, non-authoritative data is moved so 366 | that implementations looking to process only authoritative data may simply ignore 367 | the references property and fetch any data that would be contained there from its 368 | authoritative source. 369 |
370 |371 | If a property is a reference to an object that is defined authoritatively in 372 | some other location, the `references` property SHOULD be used. The property 373 | SHOULD contain only the unique identifier or URL where the authoritative data 374 | may be found. In the references object, the URL or unique identifier MAY 375 | be entered as the key field and a serialization of the referenced object MAY 376 | be provided. This serialization of the referenced object MAY be incomplete 377 | so as to provide only necessary data. 378 |
379 |380 | Parsing implementations SHOULD fetch data from the authoritative source instead of using 381 | the references object. 382 |
383 |
386 | {
387 | "type": "entry",
388 | "published": "2015-10-20T15:49:00-0700",
389 | "url": "http://example.com/post/fsjeuu8372",
390 | "author": "http://alice.example.com",
391 | "name": "Hello World",
392 | "content": "This is a blog post",
393 | "category": "Posts",
394 | "references": {
395 | "http://alice.example.com": {
396 | "type": "card",
397 | "name": "Alice",
398 | "url": "http://alice.example.com",
399 | "photo": "http://alice.example.com/photo.jpg"
400 | }
401 | }
402 | }
403 |
404 |
405 |
406 | {
407 | "type": "entry",
408 | "published": "2015-10-20T15:49:00-0700",
409 | "url": "http://example.com/like/r23eugi02c",
410 | "author": {
411 | "type": "card",
412 | "name": "Alice",
413 | "url": "http://alice.example.com",
414 | "photo": "http://alice.example.com/photo.jpg"
415 | },
416 | "like-of": "http://bob.example.com/post/100",
417 | "category": ["Likes", "Posts"],
418 | "references": {
419 | "http://bob.example.com/post/100": {
420 | "type": "entry",
421 | "published": "2015-10-18T12:33:00-0700",
422 | "url": "http://bob.example.com/post/100",
423 | "author": "http://bob.example.com",
424 | "name": "My First Post",
425 | "content": "This is my first post on my new blog, I hope you like it"
426 | },
427 | "http://bob.example.com": {
428 | "type": "card",
429 | "name": "Bob",
430 | "url": "http://bob.example.com",
431 | "photo": "http://bob.example.com/mypicture.jpg"
432 | }
433 | }
434 | }
435 |
436 | 443 | Posts can live inside of collections. A collection may be a home page feed, or a feed of other posts such as a list of contacts, a list of things someone has liked, etc. There is no requirement that all posts in a collection need to be of the same type. 444 |
445 | 446 |447 | The collection may also have its own properties such as "name" or "author". 448 |
449 | 450 |
451 | {
452 | "type": "feed",
453 | "url": "http://alice.example.com/collectionurl",
454 | "name": "Alice's Home Page",
455 | "author": {
456 | "type": "card",
457 | "name": "Alice",
458 | "url": "http://alice.example.com",
459 | "photo": "http://alice.example.com/photo"
460 | },
461 | "children": [
462 | { ... },
463 | { ... }
464 | ]
465 | }
466 |
467 |
468 | 471 | If an HTML page contains multiple top-level items, (most commonly found when a page contains a list of [[h-entry]] objects), the parser creates an implicit top-level collection with no properties. 472 |
473 | 474 |
475 | {
476 | "children": [
477 | { ... },
478 | { ... }
479 | ]
480 | }
481 |
482 |
483 | 489 | This syntax is derived from HTML with Microformats-2, converted to JSON [[microformats2-parsing]] converted to a simplified JSON. The examples below illustrate the process. 490 |
491 | 492 |497 | <article class="h-entry"> 498 | <h1 class="p-name">Hello World</h1> 499 | <p>Published by <a class="p-author h-card" href="http://example.com/">A. Developer</a> 500 | on <a href="http://example.com/2015/10/21" class="u-url"><time class="dt-published" datetime="2015-10-21T12:00:00-0700">October 21<sup>st</sup>, 2015</time></a> 501 | 502 | <p class="p-summary">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar.</p> 503 | 504 | <div class="e-content"><p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p></div> 505 | </article> 506 |507 | 508 |
511 | {
512 | "items": [
513 | {
514 | "type": [
515 | "h-entry"
516 | ],
517 | "properties": {
518 | "author": [
519 | {
520 | "type": [
521 | "h-card"
522 | ],
523 | "properties": {
524 | "name": [
525 | "A. Developer"
526 | ],
527 | "url": [
528 | "http:\/\/example.com\/"
529 | ]
530 | },
531 | "value": "A. Developer"
532 | }
533 | ],
534 | "name": [
535 | "Hello World"
536 | ],
537 | "summary": [
538 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar."
539 | ],
540 | "url": [
541 | "http:\/\/example.com\/2015\/10\/21"
542 | ],
543 | "published": [
544 | "2015-10-21T12:00:00-0700"
545 | ],
546 | "content": [
547 | {
548 | "html": "<p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p>",
549 | "value": "Donec dapibus enim lacus, a vehicula magna bibendum non. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in."
550 | }
551 | ]
552 | }
553 | }
554 | ]
555 | }
556 |
557 |
558 |
561 | {
562 | "type": "entry",
563 | "author": {
564 | "type": "card",
565 | "url": "http://example.com",
566 | "name": "A. Developer"
567 | },
568 | "url": "http://example.com/2015/10/21",
569 | "published": "2015-10-21T12:00:00-0700",
570 | "name": "Hello World",
571 | "summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar.",
572 | "content": {
573 | "value": "<p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p>",
574 | "text": "Donec dapibus enim lacus, a vehicula magna bibendum non. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in."
575 | }
576 | }
577 |
578 |
579 |
580 | 584 | JF2 documents all have an implicit @context field which is optional. This @context can be found at 585 | http://www.w3.org/ns/jf2 586 | and is provided only to make conversion to [[JSON-LD]] format possible. Most JF2 will process 587 | fine in JSON-LD systems, however, this support is not guaranteed and those wishing to 588 | use JF2 in JSON-LD may need to modify serialization slightly. 589 |
590 |597 | JF2 on its own is intentionally vocabulary independent, that is, any value may contain a single value, a 598 | set of values, or a structure and there are no requirements that fields be present. While this keeps 599 | the fidelity of the original [[microformats2]] encoded html, some consuming code can be simplified by 600 | adding vocabulary requirements. This creates the need for vocabulary aware profiles of JF2, where 601 | the profile adds additional constraints on the fields present. 602 |
603 |610 | XML formats have heavily dominated serializations of social activity feeds for blogs and news feeds for years. 611 | Several attempts have been created over the years to attempt to bring these to a JSON format, most recently 612 | [[jsonfeed-v1]], which JF2 Feed gets the majority of its requirements from. JF2 Feed is an attempt to bring 613 | some of the advantages of these vocabulary aware specifications under a standard vocabulary from 614 | [[microformats2]]. 615 |
616 | 617 |618 | Fields described below have additional requirements to be considered a valid JF2 Feed, however they may contain 619 | any number of additional fields from [[h-feed]], [[h-entry]], and [[h-card]]. The entries below are codified as 620 | they are likely the most useful for feed readers and additional data is expected to be fetchable at the entry URL, 621 | preferrably though valid [[microformats2]] markup. 622 |
623 |628 | The following fields have additional constraints to be a valid JF2 Feed that only apply 629 | to the top level feed object, its child entry object, and any properties of them. 630 |
631 | 632 |684 | The format of published and updated fields may change from [[ISO8601]] to [[RFC3339]] or use [[microformats2]]'s more liberal date field. Please discuss on github issues 685 |
686 | 687 |692 | The JF2 Feed for a page may be published as HTTP Link header [[RFC5988]], or as an HTML 693 | <link> or <a> tag element with the following attributes. 694 |
rel="alternate" type="application/jf2feed+json" href="http://www.example.com/jf2feed.json"695 | 696 |
697 | Discovery via <link> and/or <a> is being considered for removal, please leave your feedback on this via github issues. 698 |
699 |
704 | {
705 | "type": "feed",
706 | "url": "https://example.org/myfeed.html",
707 | "name": "Brent Simmons’s Microblog",
708 | "author": {
709 | "type": "card",
710 | "name": "Brent Simmons",
711 | "url": "http://example.org/",
712 | "photo": "https://example.org/avatar.png"
713 | },
714 | "children": [
715 | {
716 | "type": "entry",
717 | "uid": "https://example.org/2347259",
718 | "url": "https://example.org/2347259",
719 | "content": {
720 | "text": "Cats are neat. \n\nhttps://example.org/cats"
721 | },
722 | "published": "2016-02-09T14:22:00-07:00"
723 | }
724 | ]
725 | }
726 |
727 |
728 | 733 | As it is not sane to do this for every feed serialization currently available, 734 | this section is likely to only be temporary in the spec and may be moved to a 735 | more permanant home elsewhere. 736 |
737 | 738 |739 | JF2 Feed was based heavily on [[jsonfeed-v1]] and as such it is quite trivial to process a 740 | JSON Feed as a JF2 Feed with only minor changes. This section discusses the conversion that 741 | must be made for this process, most of which is simply conversion of properties to their 742 | [[microformats2]] equivalent. 743 |
744 | 745 |746 | Conversion of the top level sturcture 747 |
748 |757 | Conversion of the author property on the top level or on any lower level entry 758 |
759 |764 | Conversion each entry in items 765 |
766 |792 | It may be benefitial to drop any properties other than those mentioned to avoid conflicts with any future [[microformats2]] properties. 793 |
794 | 795 | 796 |803 | JF2 MAY be extended by the [[microformats2]] extension mechanism. The 'x-*' properties created in this 804 | way MAY be present in any serialization of JF2. Parsers MUST NOT halt on any unknown properties they 805 | encounter. 806 |
807 |812 | In order to allow any language to be serialized in JF2, the 'lang' value can be set on any object to inform 813 | annotate the natural language of the text. Many often ask for control structures like directionality of text 814 | and multiple language serializations. Directionality of text can be accomplished with UTF-8 control characters 815 | which can be added to any of the values in the document. In addition, any content inside of 'html' properties 816 | can have any markup as defined by [[HTML5]]. 817 |
818 |819 | Multiple serializations of the same text has not been seen to be needed in practice. 820 | The suggested path for accomplishing this with JF2 is to have these hosted at different locations. 821 | For example, it is common practice on websites to host an alternate language version of a site under a different 822 | directory structure for each language (such as /en/, /jp/, /fr/, etc). 823 |
824 |829 | The following is a list of currently known implementations of JF2-like formats and their current differences to this document 830 |
831 | 832 |835 | Webmention.io is a hosted service for handling webmentions. 836 | Webmentions are accessed from an API that that returns a set of objects in JSON format similar to JF2. 837 | The key difference is the inclusion of some additional data wrapping the objects 838 | (source, verified, verified_data, etc) and all wrapped in a "links" array. 839 | Code available at https://github.com/aaronpk/webmention.io 840 |
841 |846 | X-Ray is a tool to return structured data from any URL. 847 | Code available at https://github.com/aaronpk/XRay 848 |
849 |854 | Unmung is a tool for converting various formats. 855 | Code available at https://github.com/kevinmarks/unmung 856 |
857 |871 | Mf2util is a utility library for interpreting microformats2. 872 | Code available at https://github.com/kylewm/mf2util 873 |
874 |881 | As with any serialization format, JF2 streams can potentially contain private and personally identifiable information. 882 | As such, producing and consuming implementations SHOULD take a default stance that all information in these documents are 883 | private and take steps to ensure the privacy of their users. This can include transmission only over secure connections, 884 | limiting access to streams, deletion of stored secure information, or any other steps that would apply to any private 885 | information. 886 |
887 |893 | Publisher and Consumers of any publicly accessible or third party JF2 streams SHOULD take reasonable preventative 894 | measures to ensure against malicious code embedded in the stream and filter out such material wherever possible. 895 |
896 | 897 |898 | Publisher and Consumers of any publicly accessible or third party JF2 streams that contain HTML content SHOULD 899 | take additional steps to ensure that there is no malicious code such as cross-site scripting attacks contained 900 | in the HTML content. 901 |
902 | 903 |904 | JF2 Streams are JSON Documents and are subject to the same security considerations described in [[!RFC7159]]. 905 |
906 | 907 |application/jf2feed+json Media Type
919 | This specification registers the application/jf2feed+json MIME Media Type specifically for identifying documents
920 | conforming to the JF2 format with the JF2 Feed profile.
921 |
| Type name: | 926 |application | 927 |
| Subtype name: | 930 |jf2feed+json | 931 |
| Required parameters: | 934 |None | 935 |
| Optional parameters: | 938 |None | 939 |
| Encoding considerations: | 942 |943 | Binary, as per [[RFC6839]], section 3.1; the charset parameter is not used and byte-order marks are not permitted, as per [[RFC7159]], sections 11 and 8.1 944 | | 945 |
| Security considerations: | 948 |See [[RFC7159]] section 12 and the Security Considerations section of this specification. | 949 |
| Contact: | 952 |953 | Ben Roberts <ben@thatmustbe.me> 954 | | 955 |
This section lists changes from the 28 July 2016 FPWD to this version
969 | 970 |989 | The authors wish to thank the Microformats, IndieWebCamp, Pump.io, and Activity Streams communities for their continued work 990 | in building the social web and helping define standards such as this one. This includes, but is certainly not limited to, 991 | Aaron Parecki, 992 | Benjamin Goering, 993 | Brent Simmons, 994 | Christopher Webber, 995 | Dave Wilkinson II, 996 | James Snell, 997 | Jonathan LaCour, 998 | Kyle Mahan, 999 | Manton Reece, 1000 | Pelle Wessman, 1001 | and 1002 | Tantek Çelik. 1003 |
1004 |101 | This document describes a JSON serialization format to describe simple 102 | streams of data as well as single objects of data for data transfer and 103 | processing. 104 |
105 |122 | JF2 is a JSON based document format that describes lists and single entries 123 | of information. The primary use case for JF2 is to create a JSON format for 124 | social web post objects to be processed directly by client software and by other 125 | servers. 126 |
127 |128 | The name JF2 comes from its origins in being a direct parsed format of 129 | Microformats-2 (MF2) data from html. Rather than defining a new vocabulary, 130 | JF2 uses the vocabulary defined by [[microformats2]] 131 | however any other suitable vocabulary could be used. JF2 is vocabulary 132 | independent except for its profiles which are fully vocabulary aware. 133 |
134 |139 | JF2 has evolved as a result of a variety of use-cases for different implementations 140 | exploring ways to simplify their existing use of canonical parsed microformats2 JSON 141 | output. All of these use cases in particular are simply to have a single format for 142 | the storage and use of social web objects. 143 |
144 |145 | Webmention.io is a service that provides webmention 146 | processing and verification on behalf of other sites. It uses a simple JSON object to 147 | transfer a processed webmention back to the client site's javascript for display. The 148 | attributes are intended to be processed only by the client site's javascript code, not 149 | by anything else. 150 |
151 |152 | mf2util is a utility library that provides a layer on top 153 | of microformats processing. The library returns only a simple JSON object and strips 154 | off any unnecessary information leaving the library user only the most essential information. 155 |
156 |157 | Various services (xray, unmung, socialstreams) 158 | provide conversion from microformats pages in to JF2 for quick inspection to 159 | validate proper semantics. 160 |
161 |166 | JF2 consists of JSON objects which are defined by a type property that will specify 167 | the vocabulary of the object. Properties are attached to these objects which will contain 168 | either a single string, a single object, an array of strings, or an array of objects. 169 | Arrays that have only a single item SHOULD be condensed into only the single containing item. 170 | Any property of an object MAY be a single item or an array of items except for reserved words 171 | defined below. 172 |
173 |176 | The following keywords are reserved and cannot be used as property names in vocabularies. 177 |
178 |219 | A post is composed of a "type" property, and one or more additional properties that describe the post. 220 |
221 |222 | The "type" property has a value that describes the vocabulary of this post. Common values include "entry", "card", etc. See Microformats 2 vocabularies for the full list when using a microformats based vocabulary. 223 |
224 |225 | Any additional properties in the post object are considered part of the post's vocabulary. 226 |
227 | 228 |232 | The list of valid post properties is defined by the vocabularies. This allows new vocabularies to be developed outside the development of the syntax. 233 |
234 |235 | Most values will be strings. If a property (such as `author` for example) references another 236 | object, it may be serialized in two ways: as an object serialized as the property value or as 237 | the unique identifier or URL where the object can be found. See Using References 238 |
239 |240 | Values may also be arrays if the vocabulary allows for multiple values of the property. 241 |
242 | 243 |
248 | {
249 | "type": "entry",
250 | "published": "2015-10-20T15:49:00-0700",
251 | "url": "http://example.com/post/fsjeuu8372",
252 | "author": {
253 | "type": "card",
254 | "name": "Alice",
255 | "url": "http://alice.example.com",
256 | "photo": "http://alice.example.com/photo.jpg"
257 | },
258 | "name": "Hello World",
259 | "content": "This is a blog post",
260 | "category": "Posts"
261 | }
262 |
263 |
264 |
265 | {
266 | "type": "entry",
267 | "published": "2015-10-20T15:49:00-0700",
268 | "url": "http://example.com/like/r23eugi02c",
269 | "author": {
270 | "type": "card",
271 | "name": "Alice",
272 | "url": "http://alice.example.com",
273 | "photo": "http://alice.example.com/photo.jpg"
274 | },
275 | "like-of": "http://bob.example.com/post/100",
276 | "category": ["Likes", "Posts"]
277 | }
278 |
279 | 301 | By default, any string value should be interpreted as literal plaintext. 302 | This means when displaying a string in an HTML page, it must be HTML escaped. 303 |
304 | 305 |306 | If the value of a property is to be interpreted as HTML, it MUST be enclosed in 307 | an object and placed under the "html" property as follows. If a plaintext version 308 | is also available, that is placed under the "text" property. 309 |
310 | 311 |
312 | {
313 | "type": "entry",
314 | "content": {
315 | "html": "<p>Hello World</p>"
316 | "text": "Hello World"
317 | }
318 | }
319 |
320 |
321 | 324 | Since HTML video/audio/picture tags may have multiple URLs, we need a way to convey this information in the JSON representation. 325 |
326 | 327 |328 | <div class="h-entry"> 329 | <video class="u-video" width="640" height="360" preload controls> 330 | <source src="sample_h264.mov" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' /> 331 | <source src="sample_ogg.ogv" type='video/ogg; codecs="theora, vorbis"' /> 332 | <source src="sample_webm.webm" type='video/webm; codecs="vp8, vorbis"' /> 333 | </video> 334 | </div> 335 |336 | 337 |
338 | {
339 | "type": "entry",
340 | "video": [
341 | {
342 | "content-type": "video/mp4",
343 | "url": "sample_h264.mov"
344 | },
345 | {
346 | "content-type": "video/ogg",
347 | "url": "sample_ogg.ogg"
348 | },
349 | {
350 | "content-type": "video/webm",
351 | "url": "sample_webm.webm"
352 | }
353 | ]
354 | }
355 |
356 |
357 | 364 | The purpose of the `references` property is to exclude any non-authoritative 365 | data from the defined object. To do this, non-authoritative data is moved so 366 | that implementations looking to process only authoritative data may simply ignore 367 | the references property and fetch any data that would be contained there from its 368 | authoritative source. 369 |
370 |371 | If a property is a reference to an object that is defined authoritatively in 372 | some other location, the `references` property SHOULD be used. The property 373 | SHOULD contain only the unique identifier or URL where the authoritative data 374 | may be found. In the references object, the URL or unique identifier MAY 375 | be entered as the key field and a serialization of the referenced object MAY 376 | be provided. This serialization of the referenced object MAY be incomplete 377 | so as to provide only necessary data. 378 |
379 |380 | Parsing implementations SHOULD fetch data from the authoritative source instead of using 381 | the references object. 382 |
383 |
386 | {
387 | "type": "entry",
388 | "published": "2015-10-20T15:49:00-0700",
389 | "url": "http://example.com/post/fsjeuu8372",
390 | "author": "http://alice.example.com",
391 | "name": "Hello World",
392 | "content": "This is a blog post",
393 | "category": "Posts",
394 | "references": {
395 | "http://alice.example.com": {
396 | "type": "card",
397 | "name": "Alice",
398 | "url": "http://alice.example.com",
399 | "photo": "http://alice.example.com/photo.jpg"
400 | }
401 | }
402 | }
403 |
404 |
405 |
406 | {
407 | "type": "entry",
408 | "published": "2015-10-20T15:49:00-0700",
409 | "url": "http://example.com/like/r23eugi02c",
410 | "author": {
411 | "type": "card",
412 | "name": "Alice",
413 | "url": "http://alice.example.com",
414 | "photo": "http://alice.example.com/photo.jpg"
415 | },
416 | "like-of": "http://bob.example.com/post/100",
417 | "category": ["Likes", "Posts"],
418 | "references": {
419 | "http://bob.example.com/post/100": {
420 | "type": "entry",
421 | "published": "2015-10-18T12:33:00-0700",
422 | "url": "http://bob.example.com/post/100",
423 | "author": "http://bob.example.com",
424 | "name": "My First Post",
425 | "content": "This is my first post on my new blog, I hope you like it"
426 | },
427 | "http://bob.example.com": {
428 | "type": "card",
429 | "name": "Bob",
430 | "url": "http://bob.example.com",
431 | "photo": "http://bob.example.com/mypicture.jpg"
432 | }
433 | }
434 | }
435 |
436 | 443 | Posts can live inside of collections. A collection may be a home page feed, or a feed of other posts such as a list of contacts, a list of things someone has liked, etc. There is no requirement that all posts in a collection need to be of the same type. 444 |
445 | 446 |447 | The collection may also have its own properties such as "name" or "author". 448 |
449 | 450 |
451 | {
452 | "type": "feed",
453 | "url": "http://alice.example.com/collectionurl",
454 | "name": "Alice's Home Page",
455 | "author": {
456 | "type": "card",
457 | "name": "Alice",
458 | "url": "http://alice.example.com",
459 | "photo": "http://alice.example.com/photo"
460 | },
461 | "children": [
462 | { ... },
463 | { ... }
464 | ]
465 | }
466 |
467 |
468 | 471 | If an HTML page contains multiple top-level items, (most commonly found when a page contains a list of [[h-entry]] objects), the parser creates an implicit top-level collection with no properties. 472 |
473 | 474 |
475 | {
476 | "children": [
477 | { ... },
478 | { ... }
479 | ]
480 | }
481 |
482 |
483 | 489 | This syntax is derived from HTML with Microformats-2, converted to JSON [[microformats2-parsing]] converted to a simplified JSON. The examples below illustrate the process. 490 |
491 | 492 |497 | <article class="h-entry"> 498 | <h1 class="p-name">Hello World</h1> 499 | <p>Published by <a class="p-author h-card" href="http://example.com/">A. Developer</a> 500 | on <a href="http://example.com/2015/10/21" class="u-url"><time class="dt-published" datetime="2015-10-21T12:00:00-0700">October 21<sup>st</sup>, 2015</time></a> 501 | 502 | <p class="p-summary">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar.</p> 503 | 504 | <div class="e-content"><p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p></div> 505 | </article> 506 |507 | 508 |
511 | {
512 | "items": [
513 | {
514 | "type": [
515 | "h-entry"
516 | ],
517 | "properties": {
518 | "author": [
519 | {
520 | "type": [
521 | "h-card"
522 | ],
523 | "properties": {
524 | "name": [
525 | "A. Developer"
526 | ],
527 | "url": [
528 | "http:\/\/example.com\/"
529 | ]
530 | },
531 | "value": "A. Developer"
532 | }
533 | ],
534 | "name": [
535 | "Hello World"
536 | ],
537 | "summary": [
538 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar."
539 | ],
540 | "url": [
541 | "http:\/\/example.com\/2015\/10\/21"
542 | ],
543 | "published": [
544 | "2015-10-21T12:00:00-0700"
545 | ],
546 | "content": [
547 | {
548 | "html": "<p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p>",
549 | "value": "Donec dapibus enim lacus, a vehicula magna bibendum non. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in."
550 | }
551 | ]
552 | }
553 | }
554 | ]
555 | }
556 |
557 |
558 |
561 | {
562 | "type": "entry",
563 | "author": {
564 | "type": "card",
565 | "url": "http://example.com",
566 | "name": "A. Developer"
567 | },
568 | "url": "http://example.com/2015/10/21",
569 | "published": "2015-10-21T12:00:00-0700",
570 | "name": "Hello World",
571 | "summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar.",
572 | "content": {
573 | "value": "<p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p>",
574 | "text": "Donec dapibus enim lacus, a vehicula magna bibendum non. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in."
575 | }
576 | }
577 |
578 |
579 |
580 | 584 | JF2 documents all have an implicit @context field which is optional. This @context can be found at 585 | http://www.w3.org/ns/jf2 586 | and is provided only to make conversion to [[JSON-LD]] format possible. Most JF2 will process 587 | fine in JSON-LD systems, however, this support is not guaranteed and those wishing to 588 | use JF2 in JSON-LD may need to modify serialization slightly. 589 |
590 |597 | JF2 on its own is intentionally vocabulary independent, that is, any value may contain a single value, a 598 | set of values, or a structure and there are no requirements that fields be present. While this keeps 599 | the fidelity of the original [[microformats2]] encoded html, some consuming code can be simplified by 600 | adding vocabulary requirements. This creates the need for vocabulary aware profiles of JF2, where 601 | the profile adds additional constraints on the fields present. 602 |
603 |610 | XML formats have heavily dominated serializations of social activity feeds for blogs and news feeds for years. 611 | Several attempts have been created over the years to attempt to bring these to a JSON format, most recently 612 | [[jsonfeed-v1]], which JF2 Feed gets the majority of its requirements from. JF2 Feed is an attempt to bring 613 | some of the advantages of these vocabulary aware specifications under a standard vocabulary from 614 | [[microformats2]]. 615 |
616 | 617 |618 | Fields described below have additional requirements to be considered a valid JF2 Feed, however they may contain 619 | any number of additional fields from [[h-feed]], [[h-entry]], and [[h-card]]. The entries below are codified as 620 | they are likely the most useful for feed readers and additional data is expected to be fetchable at the entry URL, 621 | preferrably though valid [[microformats2]] markup. 622 |
623 |628 | The following fields have additional constraints to be a valid JF2 Feed that only apply 629 | to the top level feed object, its child entry object, and any properties of them. 630 |
631 | 632 |684 | The format of published and updated fields may change from [[ISO8601]] to [[RFC3339]] or use [[microformats2]]'s more liberal date field. Please discuss on github issues 685 |
686 | 687 |692 | The JF2 Feed for a page may be published as HTTP Link header [[RFC5988]], or as an HTML 693 | <link> or <a> tag element with the following attributes. 694 |
rel="alternate" type="application/jf2feed+json" href="http://www.example.com/jf2feed.json"695 | 696 |
701 | {
702 | "type": "feed",
703 | "url": "https://example.org/myfeed.html",
704 | "name": "Brent Simmons’s Microblog",
705 | "author": {
706 | "type": "card",
707 | "name": "Brent Simmons",
708 | "url": "http://example.org/",
709 | "photo": "https://example.org/avatar.png"
710 | },
711 | "children": [
712 | {
713 | "type": "entry",
714 | "uid": "https://example.org/2347259",
715 | "url": "https://example.org/2347259",
716 | "content": {
717 | "text": "Cats are neat. \n\nhttps://example.org/cats"
718 | },
719 | "published": "2016-02-09T14:22:00-07:00"
720 | }
721 | ]
722 | }
723 |
724 |
725 | 730 | As it is not sane to do this for every feed serialization currently available, 731 | this section is likely to only be temporary in the spec and may be moved to a 732 | more permanant home elsewhere. 733 |
734 | 735 |736 | JF2 Feed was based heavily on [[jsonfeed-v1]] and as such it is quite trivial to process a 737 | JSON Feed as a JF2 Feed with only minor changes. This section discusses the conversion that 738 | must be made for this process, most of which is simply conversion of properties to their 739 | [[microformats2]] equivalent. 740 |
741 | 742 |743 | Conversion of the top level sturcture 744 |
745 |754 | Conversion of the author property on the top level or on any lower level entry 755 |
756 |761 | Conversion each entry in items 762 |
763 |789 | It may be benefitial to drop any properties other than those mentioned to avoid conflicts with any future [[microformats2]] properties. 790 |
791 | 792 | 793 |800 | JF2 MAY be extended by the [[microformats2]] extension mechanism. The 'x-*' properties created in this 801 | way MAY be present in any serialization of JF2. Parsers MUST NOT halt on any unknown properties they 802 | encounter. 803 |
804 |809 | In order to allow any language to be serialized in JF2, the 'lang' value can be set on any object to inform 810 | annotate the natural language of the text. Many often ask for control structures like directionality of text 811 | and multiple language serializations. Directionality of text can be accomplished with UTF-8 control characters 812 | which can be added to any of the values in the document. In addition, any content inside of 'html' properties 813 | can have any markup as defined by [[HTML5]]. 814 |
815 |816 | Multiple serializations of the same text has not been seen to be needed in practice. 817 | The suggested path for accomplishing this with JF2 is to have these hosted at different locations. 818 | For example, it is common practice on websites to host an alternate language version of a site under a different 819 | directory structure for each language (such as /en/, /jp/, /fr/, etc). 820 |
821 |826 | The following is a list of currently known implementations of JF2-like formats and their current differences to this document 827 |
828 | 829 |832 | Webmention.io is a hosted service for handling webmentions. 833 | Webmentions are accessed from an API that that returns a set of objects in JSON format similar to JF2. 834 | The key difference is the inclusion of some additional data wrapping the objects 835 | (source, verified, verified_data, etc) and all wrapped in a "links" array. 836 | Code available at https://github.com/aaronpk/webmention.io 837 |
838 |843 | X-Ray is a tool to return structured data from any URL. 844 | Code available at https://github.com/aaronpk/XRay 845 |
846 |851 | Unmung is a tool for converting various formats. 852 | Code available at https://github.com/kevinmarks/unmung 853 |
854 |868 | Mf2util is a utility library for interpreting microformats2. 869 | Code available at https://github.com/kylewm/mf2util 870 |
871 |878 | As with any serialization format, JF2 streams can potentially contain private and personally identifiable information. 879 | As such, producing and consuming implementations SHOULD take a default stance that all information in these documents are 880 | private and take steps to ensure the privacy of their users. This can include transmission only over secure connections, 881 | limiting access to streams, deletion of stored secure information, or any other steps that would apply to any private 882 | information. 883 |
884 |890 | JF2 is not intended to contain executable code however, as JF2 allows arbitrary text it may be possible for publishers 891 | to craft text in an executable fashion. As such, JF2 documents should not be passed through any executable mechanism 892 | such as javascripts eval() function to be parsed. Processing of field contents should not execute any encountered code 893 | and it is recommended that any HTML formatted content be filtered to remove any executable code such as script and style tags. 894 |
895 | 896 |897 | JF2 documents may require privacy and integrity services depending on the document content and implementation 898 | concerns. If such services are required, they must be provided externally such as by the use of SSL/TLS connections 899 | to prevent forgery or exposure of data. 900 |
901 | 902 |903 | Any externally linked documents must be processed by their own format's security model. JF2 documents do not make any claims 904 | about the security of any externally referenced documents. 905 |
906 | 907 |908 | JF2 Streams are JSON Documents and are subject to the same security considerations described in [[!RFC7159]]. 909 |
910 | 911 |application/jf2feed+json Media Type
923 | This specification registers the application/jf2feed+json MIME Media Type specifically for identifying documents
924 | conforming to the JF2 format with the JF2 Feed profile.
925 |
| Type name: | 930 |application | 931 |
| Subtype name: | 934 |jf2feed+json | 935 |
| Required parameters: | 938 |None | 939 |
| Optional parameters: | 942 |None | 943 |
| Encoding considerations: | 946 |947 | Binary, as per [[RFC6839]], section 3.1; the charset parameter is not used and byte-order marks are not permitted, as per [[RFC7159]], sections 11 and 8.1 948 | | 949 |
| Security considerations: | 952 |See [[RFC7159]] section 12 and the Security Considerations section of this specification. | 953 |
| Contact: | 956 |957 | Ben Roberts <ben@thatmustbe.me> 958 | | 959 |
This section lists changes from the 12 June 2017 FPWD to this version.
973 | 974 |This section lists changes from the 28 July 2016 FPWD to 12 June 2017 WD
984 | 985 |1004 | The authors wish to thank the Microformats, IndieWebCamp, Pump.io, and Activity Streams communities for their continued work 1005 | in building the social web and helping define standards such as this one. This includes, but is certainly not limited to, 1006 | Aaron Parecki, 1007 | Benjamin Goering, 1008 | Brent Simmons, 1009 | Christopher Webber, 1010 | Dave Wilkinson II, 1011 | James Snell, 1012 | Jonathan LaCour, 1013 | Kyle Mahan, 1014 | Manton Reece, 1015 | Pelle Wessman, 1016 | and 1017 | Tantek Çelik. 1018 |
1019 |88 | This document describes a JSON serialization format to describe simple 89 | streams of data as well as single objects of data for data transfer and 90 | processing. 91 |
92 |111 | JF2 is a JSON based document format that describes single entries of 112 | information and lists of those entries. The primary use case for JF2 is to 113 | create a JSON format for social web post objects to be processed directly by 114 | client software and by other servers. 115 |
116 |117 | JF2 is vocabulary independent except for its profiles which are fully 118 | vocabulary aware. Rather than defining a new vocabulary the profiles 119 | described in this document use the vocabulary defined by [[microformats2]] 120 | (MF2); however, any other suitable vocabulary could be used. The name JF2 121 | comes from its origins in being a direct parsed format of microformats2 data 122 | from HTML. 123 |
124 |129 | JF2 has evolved as a result of a variety of use-cases for different implementations 130 | exploring ways to simplify their existing use of canonical parsed microformats2 JSON 131 | output. All of these use cases in particular are simply to have a single format for 132 | the storage and use of social web objects. 133 |
134 |135 | Webmention.io is a service that provides Webmention 136 | processing and verification on behalf of other sites. It uses a simple JSON object to 137 | transfer a processed Webmention back to the client site's JavaScript for display. The 138 | attributes are intended to be processed only by the client site's JavaScript code, not 139 | by anything else. 140 |
141 |142 | mf2util is a utility library that provides a layer on top 143 | of microformats processing. The library returns only a simple JSON object and strips 144 | off any unnecessary information leaving the library user only the most essential information. 145 |
146 |147 | Various services (XRay, 148 | Unmung, 149 | SocialStreams) 150 | provide conversion from microformats pages into JF2 for quick inspection to 151 | validate proper semantics. These tools have been used in practice to allow for embedded social activity in a page. 152 |
153 |161 | Conforming documents are those that comply with all the conformance 162 | criteria for JF2 documents. For readability, some of these conformance 163 | requirements are phrased as conformance requirements on publishers. 164 | Such requirements are implicitly requirements on documents: by 165 | definition, all documents are assumed to have a publisher. 166 |
167 | 168 |169 | Conforming documents must not use features of JSON-LD or other 170 | serialization features disallowed in this specification. Conforming 171 | documents that include types or properties beyond those defined in 172 | [[microformats2]] must use [[microformats2]]'s prefixing methods to indicate 173 | non-standard properties. 174 |
175 | 176 |177 | A non-exhaustive list of examples of documents includes: 178 | 179 |
180 |210 | Conforming implementations are software that publish, store, analyze, 211 | consume or otherwise process conforming documents. The two main kinds 212 | of implementations are publishers and consumers. 213 |
214 | 215 |220 | Conforming publishers are implementations that create and publish 221 | conforming documents. Conforming publishers must make conforming 222 | documents available according to the serialization requirements of 223 | this document. Conforming publishers must consider privacy as described 224 | in the Privacy section of this document. 225 | Conforming publishers must consider security as described in the 226 | Security Considerations section 227 | of this document. 228 |
229 | 230 |231 | A non-exhaustive list of example publishers includes: 232 |
233 | 234 |260 | Conforming consumers are implementations that read and analyze 261 | conforming documents. Conforming consumers must not halt on any 262 | unrecognized properties or types. 263 |
264 | 265 |266 | Conforming consumers may re-publish conforming documents in other 267 | other data formats. Conforming consumers may present conforming 268 | documents to a user on screen, in print, in audio format, or using 269 | other presentation mechanisms. Conforming consumers must faithfully 270 | translate the information represented in conforming documents into 271 | these other formats or media. Conforming consumers that re-publish 272 | conforming documents must consider privacy and security as described 273 | in the Privacy section and 274 | Security Considerations section 275 | of this document. 276 |
277 | 278 |A non-exhaustive list of example consumers includes:
279 | 280 |305 | A validator for conforming documents is available at 306 | https://jf2.rocks/. 307 | This also offers example conforming and non-conforming 308 | documents for testing purposes. 309 |
310 | 311 |312 | Please submit your implementation reports at 313 | https://jf2.rocks/. 314 | Instructions are provided at the URL. 315 |
316 | 317 |326 | JF2 consists of JSON objects which are defined by a type property that will specify 327 | the vocabulary of the object. Properties are attached to these objects which will contain 328 | either a single string, a single object, an array of strings, or an array of objects. 329 | Arrays that have only a single item SHOULD be condensed into only the single containing item. 330 | Any property of an object MAY be a single item or an array of items except for reserved properties 331 | defined below. 332 |
333 |336 | The following properties are reserved and cannot be used as property names in vocabularies. 337 |
338 |375 | A post is composed of a "type" property, and one or more additional properties that describe the post. 376 |
377 |378 | The "type" property has a value that describes the vocabulary of the post. Common values include "entry", "card", etc. 379 | See microformats2 vocabularies 380 | for the full list when using a microformats based vocabulary. 381 |
382 |383 | Any additional properties in the post object are considered part of the post's vocabulary. 384 |
385 | 386 |390 | The list of valid post properties is defined by the vocabularies. This allows new vocabularies to be developed outside the development of the syntax. 391 |
392 |393 | Most values will be strings. If a property (such as "author" for example) references another 394 | object, it may be serialized in two ways: as an inline JSON object or as the unique identifier 395 | or [[!URL]] where the object can be found. See Using References. 396 |
397 |398 | Values MAY also be arrays if the vocabulary allows for multiple values of the property. 399 |
400 | 401 |
406 | {
407 | "type": "entry",
408 | "published": "2015-10-20T15:49:00-0700",
409 | "url": "https://example.com/post/fsjeuu8372",
410 | "author": {
411 | "type": "card",
412 | "name": "Alice",
413 | "url": "https://alice.example.com",
414 | "photo": "https://alice.example.com/photo.jpg"
415 | },
416 | "name": "Hello World",
417 | "content": "This is a blog post",
418 | "category": "Posts"
419 | }
420 |
421 |
422 |
423 | {
424 | "type": "entry",
425 | "published": "2015-10-20T15:49:00-0700",
426 | "url": "https://example.com/like/r23eugi02c",
427 | "author": {
428 | "type": "card",
429 | "name": "Alice",
430 | "url": "https://alice.example.com",
431 | "photo": "https://alice.example.com/photo.jpg"
432 | },
433 | "like-of": "https://bob.example.com/post/100",
434 | "category": ["Likes", "Posts"]
435 | }
436 |
437 | 460 | By default, any string value should be interpreted as literal plaintext. 461 | This means when displaying a string in an HTML page, it must be HTML escaped. 462 |
463 | 464 |465 | If the value of a property is to be interpreted as HTML, it MUST be enclosed in 466 | an object and placed under the "html" property as follows. If a plaintext version 467 | is also available, that is placed under the "text" property. 468 |
469 | 470 |
471 | {
472 | "type": "entry",
473 | "content": {
474 | "html": "<p>Hello World</p>",
475 | "text": "Hello World"
476 | }
477 | }
478 |
479 |
480 | 483 | Since HTML video/audio/picture tags may have multiple URLs, we need a way to convey this information in the JSON representation. 484 | In such situations, vocabulary properties MAY be arrays. 485 |
486 | 487 |488 | For example, this HTML (marked up with microformats2): 489 |
490 | 491 |492 | <div class="h-entry"> 493 | <video class="u-video" width="640" height="360" preload controls> 494 | <source src="sample_h264.mov" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' /> 495 | <source src="sample_ogg.ogv" type='video/ogg; codecs="theora, vorbis"' /> 496 | <source src="sample_webm.webm" type='video/webm; codecs="vp8, vorbis"' /> 497 | </video> 498 | </div> 499 |500 | 501 |
502 | could be represented with this JSON: 503 |
504 | 505 |
506 | {
507 | "type": "entry",
508 | "video": [
509 | {
510 | "content-type": "video/mp4",
511 | "url": "sample_h264.mov"
512 | },
513 | {
514 | "content-type": "video/ogg",
515 | "url": "sample_ogg.ogg"
516 | },
517 | {
518 | "content-type": "video/webm",
519 | "url": "sample_webm.webm"
520 | }
521 | ]
522 | }
523 |
524 |
525 | 532 | The purpose of the references property is to exclude any non-authoritative 533 | data from the defined object. To do this, non-authoritative data is moved so 534 | that implementations looking to process only authoritative data may simply ignore 535 | the references property and fetch any data that would be contained there from its 536 | authoritative source. 537 |
538 |539 | If a property is a reference to an object that is defined authoritatively in 540 | some other location, the references property SHOULD be used. The property 541 | SHOULD contain only the unique identifier or [[!URL]] where the authoritative data 542 | may be found. In the references object, the URL or unique identifier MAY 543 | be used as the property key and a serialization of the referenced object MAY 544 | be provided as the property value. This serialization of the referenced object MAY 545 | be incomplete so as to provide only necessary data. 546 |
547 |548 | Parsing implementations SHOULD fetch data from the authoritative source instead of using 549 | the references object. 550 |
551 |
554 | {
555 | "type": "entry",
556 | "published": "2015-10-20T15:49:00-0700",
557 | "url": "https://example.com/post/fsjeuu8372",
558 | "author": "https://alice.example.com",
559 | "name": "Hello World",
560 | "content": "This is a blog post",
561 | "category": "Posts",
562 | "references": {
563 | "https://alice.example.com": {
564 | "type": "card",
565 | "name": "Alice",
566 | "url": "https://alice.example.com",
567 | "photo": "https://alice.example.com/photo.jpg"
568 | }
569 | }
570 | }
571 |
572 |
573 |
574 | {
575 | "type": "entry",
576 | "published": "2015-10-20T15:49:00-0700",
577 | "url": "https://example.com/like/r23eugi02c",
578 | "author": {
579 | "type": "card",
580 | "name": "Alice",
581 | "url": "https://alice.example.com",
582 | "photo": "https://alice.example.com/photo.jpg"
583 | },
584 | "like-of": "https://bob.example.com/post/100",
585 | "category": ["Likes", "Posts"],
586 | "references": {
587 | "https://bob.example.com/post/100": {
588 | "type": "entry",
589 | "published": "2015-10-18T12:33:00-0700",
590 | "url": "https://bob.example.com/post/100",
591 | "author": "https://bob.example.com",
592 | "name": "My First Post",
593 | "content": "This is my first post on my new blog, I hope you like it"
594 | },
595 | "https://bob.example.com": {
596 | "type": "card",
597 | "name": "Bob",
598 | "url": "https://bob.example.com",
599 | "photo": "https://bob.example.com/mypicture.jpg"
600 | }
601 | }
602 | }
603 |
604 | 611 | Posts can be contained inside of collections. A collection may be a home page feed, or a feed of other posts such as a list of contacts, a list of things someone has liked, etc. There is no requirement that all posts in a collection need to be of the same type. 612 |
613 | 614 |615 | The collection may also have its own properties such as "name" or "author". 616 |
617 | 618 |
619 | {
620 | "type": "feed",
621 | "url": "https://alice.example.com/collectionurl",
622 | "name": "Alice's Home Page",
623 | "author": {
624 | "type": "card",
625 | "name": "Alice",
626 | "url": "https://alice.example.com",
627 | "photo": "https://alice.example.com/photo"
628 | },
629 | "children": [
630 | {
631 | "type": "entry",
632 | "content": {
633 | "html": "Hello World
",
634 | "text": "Hello World"
635 | }
636 | },
637 | {
638 | "type": "entry",
639 | "content": {
640 | "html": "A Second Post
",
641 | "text": "A Second Post"
642 | }
643 | }
644 | ]
645 | }
646 |
647 |
648 | 651 | If an HTML page contains multiple top-level items, (most commonly found when a page contains a list of [[h-entry]] objects), the parser creates an implicit top-level collection with no properties. 652 |
653 | 654 |
655 | {
656 | "children": [
657 | {
658 | "type": "entry",
659 | "content": {
660 | "html": "Hello World
",
661 | "text": "Hello World"
662 | }
663 | },
664 | {
665 | "type": "entry",
666 | "content": {
667 | "html": "A Second Post
",
668 | "text": "A Second Post"
669 | }
670 | }
671 | ]
672 | }
673 |
674 |
675 | 681 | This syntax is derived from HTML with microformats2 converted to JSON with [[!microformats2-parsing]], then converted to a simplified JSON. The examples below illustrate the process. 682 |
683 | 684 |689 | <article class="h-entry"> 690 | <h1 class="p-name">Hello World</h1> 691 | <p>Published by <a class="p-author h-card" href="https://example.com/">A. Developer</a> 692 | on <a href="https://example.com/2015/10/21" class="u-url"><time class="dt-published" datetime="2015-10-21T12:00:00-0700">October 21<sup>st</sup>, 2015</time></a> 693 | 694 | <p class="p-summary">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar.</p> 695 | 696 | <div class="e-content"><p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p></div> 697 | </article> 698 |699 | 700 |
703 | {
704 | "items": [
705 | {
706 | "type": [
707 | "h-entry"
708 | ],
709 | "properties": {
710 | "author": [
711 | {
712 | "type": [
713 | "h-card"
714 | ],
715 | "properties": {
716 | "name": [
717 | "A. Developer"
718 | ],
719 | "url": [
720 | "https://example.com/"
721 | ]
722 | },
723 | "value": "A. Developer"
724 | }
725 | ],
726 | "name": [
727 | "Hello World"
728 | ],
729 | "summary": [
730 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar."
731 | ],
732 | "url": [
733 | "https://example.com/2015/10/21"
734 | ],
735 | "published": [
736 | "2015-10-21T12:00:00-0700"
737 | ],
738 | "content": [
739 | {
740 | "html": "<p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p>",
741 | "value": "Donec dapibus enim lacus, a vehicula magna bibendum non. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in."
742 | }
743 | ]
744 | }
745 | }
746 | ]
747 | }
748 |
749 |
750 |
753 | {
754 | "type": "entry",
755 | "author": {
756 | "type": "card",
757 | "url": "https://example.com",
758 | "name": "A. Developer"
759 | },
760 | "url": "https://example.com/2015/10/21",
761 | "published": "2015-10-21T12:00:00-0700",
762 | "name": "Hello World",
763 | "summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus imperdiet ultrices pulvinar.",
764 | "content": {
765 | "html": "<p>Donec dapibus enim lacus, <i>a vehicula magna bibendum non</i>. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in.</p>",
766 | "text": "Donec dapibus enim lacus, a vehicula magna bibendum non. Phasellus id lacinia felis, vitae pellentesque enim. Sed at quam dui. Suspendisse accumsan, est id pulvinar consequat, urna ex tincidunt enim, nec sodales lectus nulla et augue. Cras venenatis vehicula molestie. Donec sagittis elit orci, sit amet egestas ex pharetra in."
767 | }
768 | }
769 |
770 |
771 |
772 | 776 | JF2 documents all have an implicit @context field which is optional. This @context can be found at 777 | https://www.w3.org/ns/jf2 778 | and is provided only to make conversion to [[JSON-LD]] format possible. Most JF2 will process 779 | fine in JSON-LD systems, however, this support is not guaranteed and those wishing to 780 | use JF2 in JSON-LD may need to modify serialization slightly. 781 |
782 |789 | JF2 on its own is intentionally vocabulary independent, that is, any value may contain a single value, a 790 | set of values, or a structure and there are no requirements that fields be present. While this keeps 791 | the fidelity of the original [[microformats2]] encoded HTML, some consuming code can be simplified by 792 | adding vocabulary requirements. This creates the need for vocabulary aware profiles of JF2, where 793 | the profile adds additional constraints on the fields present. 794 |
795 |802 | XML formats have heavily dominated serializations of social activity feeds for blogs and news feeds for years. 803 | Several attempts have been created over the years to attempt to bring these to a JSON format, most recently 804 | [[jsonfeed-v1]], which JF2 Feed gets the majority of its requirements from. JF2 Feed is an attempt to bring 805 | some of the advantages of these vocabulary aware specifications under a standard vocabulary from 806 | [[microformats2]]. 807 |
808 | 809 |810 | Fields described below have additional requirements to be considered a valid JF2 Feed, however they may contain 811 | any number of additional fields from [[h-feed]], [[h-entry]], and [[h-card]]. The fields below are codified as 812 | they are likely the most useful for feed readers; additional data is expected to be fetchable at the entry URL, 813 | preferably though valid [[microformats2]] markup. 814 |
815 |820 | The following fields have additional constraints to be a valid JF2 Feed that only apply 821 | to the top level feed object, its child entry object, and any properties of them. 822 |
823 | 824 |876 | The format of published and updated fields may change from [[ISO8601]] to [[RFC3339]] or use [[microformats2]]'s more liberal date field. Please discuss on github issues 877 |
878 | 879 |884 | The JF2 Feed for a page may be published as HTTP Link header [[!RFC5988]], or as an HTML 885 | <link> or <a> tag element with the following attributes. 886 |
rel="alternate" type="application/jf2feed+json" href="https://example.com/jf2feed.json"887 | 888 |
893 | {
894 | "type": "feed",
895 | "url": "https://example.org/myfeed.html",
896 | "name": "Brent Simmons’s Microblog",
897 | "author": {
898 | "type": "card",
899 | "name": "Brent Simmons",
900 | "url": "https://example.org/",
901 | "photo": "https://example.org/avatar.png"
902 | },
903 | "children": [
904 | {
905 | "type": "entry",
906 | "uid": "https://example.org/2347259",
907 | "url": "https://example.org/2347259",
908 | "content": {
909 | "text": "Cats are neat. \n\nhttps://example.org/cats"
910 | },
911 | "published": "2016-02-09T14:22:00-07:00"
912 | }
913 | ]
914 | }
915 |
916 |
917 | 922 | As it is not sane to do this for every feed serialization currently available, 923 | this section is likely to only be temporary in the spec and may be moved to a 924 | more permanant home elsewhere. 925 |
926 | 927 |928 | JF2 Feed was based heavily on [[jsonfeed-v1]] and as such it is quite trivial to process a 929 | JSON Feed as a JF2 Feed with only minor changes. This section discusses the conversion that 930 | must be made for this process, most of which is simply conversion of properties to their 931 | [[microformats2]] equivalent. 932 |
933 | 934 |935 | Conversion of the top level structure 936 |
937 |946 | Conversion of the author property on the top level or on any lower level entry 947 |
948 |953 | Conversion of each entry in items 954 |
955 |981 | It may be beneficial to drop any properties other than those mentioned to avoid conflicts with any future [[microformats2]] properties. 982 |
983 | 984 | 985 |992 | JF2 MAY be extended by the [[!microformats2]] extension mechanism. The 'x-*' properties created in this 993 | way MAY be present in any serialization of JF2. Parsers MUST NOT halt on any unknown properties they 994 | encounter. 995 |
996 |1001 | In order to allow any language to be serialized in JF2, the 'lang' value can be set on any object to annotate 1002 | the natural language of the text. Many often ask for control structures like directionality of text and 1003 | multiple language serializations. Directionality of text can be accomplished with UTF-8 control characters 1004 | which can be added to any of the values in the document. In addition, any content inside of 'html' properties 1005 | can have any markup as defined by [[!HTML5]]. 1006 |
1007 |1008 | Multiple serializations of the same text has not been seen to be needed in practice. 1009 | The suggested path for accomplishing this with JF2 is to have these hosted at different locations. 1010 | For example, it is common practice on websites to host an alternate language version of a site under a different 1011 | directory structure for each language (such as /en/, /jp/, /fr/, etc). 1012 |
1013 |1019 | As with any serialization format, JF2 streams can potentially contain private and personally identifiable information. 1020 | As such, producing and consuming implementations SHOULD take a default stance that all information in these documents are 1021 | private and take steps to ensure the privacy of their users. This can include transmission only over secure connections, 1022 | limiting access to streams, deletion of stored secure information, or any other steps that would apply to any private 1023 | information. 1024 |
1025 |1031 | JF2 is not intended to contain executable code however, as JF2 allows arbitrary text it may be possible for publishers 1032 | to craft text in an executable fashion. As such, JF2 documents should not be passed through any executable mechanism 1033 | such as JavaScript's eval() function to be parsed. Processing of field contents should not execute any encountered code 1034 | and it is recommended that any HTML formatted content be filtered to remove any executable code such as script and style tags. 1035 |
1036 | 1037 |1038 | JF2 documents may require privacy and integrity services depending on the document content and implementation 1039 | concerns. If such services are required, they must be provided externally such as by the use of SSL/TLS connections 1040 | to prevent forgery or exposure of data. 1041 |
1042 | 1043 |1044 | Any externally linked documents must be processed by their own format's security model. JF2 documents do not make any claims 1045 | about the security of any externally referenced documents. 1046 |
1047 | 1048 |1049 | JF2 Streams are JSON Documents and are subject to the same security considerations described in [[!RFC7159]]. 1050 |
1051 | 1052 |application/jf2feed+json Media Type
1064 | This specification registers the application/jf2feed+json MIME Media Type specifically for identifying documents
1065 | conforming to the JF2 format with the JF2 Feed profile.
1066 |
| Type name: | 1071 |application | 1072 |
| Subtype name: | 1075 |jf2feed+json | 1076 |
| Required parameters: | 1079 |None | 1080 |
| Optional parameters: | 1083 |None | 1084 |
| Encoding considerations: | 1087 |1088 | Binary, as per [[!RFC6839]], section 3.1; the charset parameter is not used and byte-order marks are not permitted, as per [[!RFC7159]], sections 11 and 8.1 1089 | | 1090 |
| Security considerations: | 1093 |See [[RFC7159]] section 12 and the Security Considerations section of this specification. | 1094 |
| Contact: | 1097 |1098 | Bebe Roberts <bebe@thatmustbe.me> 1099 | | 1100 |
This section lists changes from the 26 Oct 2017 WD to this version.
1114 | 1115 |This section lists changes from the 19 July 2017 WD to 26 Oct 2017 WD.
1126 | 1127 |This section lists changes from the 27 June 2017 WD to 19 July 2017 WD.
1138 | 1139 |This section lists changes from the 12 June 2017 WD to 27 June 2017 WD.
1150 | 1151 |This section lists changes from the 28 July 2016 FPWD to 12 June 2017 WD
1161 | 1162 |1181 | The authors wish to thank the Microformats, IndieWeb, Pump.io, and Activity Streams communities for their continued work 1182 | in building the social web and helping define standards such as this one. This includes, but is certainly not limited to, 1183 | Aaron Parecki, 1184 | AJ Jordan, 1185 | Benjamin Goering, 1186 | Brent Simmons, 1187 | Christine Webber, 1188 | Dave Wilkinson II, 1189 | James Snell, 1190 | Jonathan LaCour, 1191 | Kara Mahan, 1192 | Manton Reece, 1193 | Pelle Wessman, 1194 | and 1195 | Tantek Çelik. 1196 |
1197 |
SocialStreams
609 |610 | SocialStreams is a translation service for converting social formats. 611 | Code available at https://github.com/dissolve/socialstream 612 |
613 |