From d1a897419c7fea6fae94a0cb0eeaf0e5f3dba3d2 Mon Sep 17 00:00:00 2001 From: Ethan Resnick Date: Sun, 7 Oct 2018 13:56:31 -0400 Subject: [PATCH 1/8] fix(format): remove "extensions" reference from example url MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we’re calling them ‘profiles’ now. --- _format/1.1/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_format/1.1/index.md b/_format/1.1/index.md index bcb5268c3..814bbcf52 100644 --- a/_format/1.1/index.md +++ b/_format/1.1/index.md @@ -1893,10 +1893,10 @@ request is received, a server **SHOULD** attempt to apply the requested profiles to its response. For example, in the following request, the client asks that the server apply the -`http://jsonapi.org/extensions/last-modified` profile if it is able to. +`http://example.com/last-modified` profile if it is able to. ```http -Accept: application/vnd.api+json;profile="http://example.com/extensions/last-modified", application/vnd.api+json +Accept: application/vnd.api+json;profile="http://example.com/last-modified", application/vnd.api+json ``` > Note: The second instance of the JSON API media type in the example above is From 170b579c1d9b7c36547b0fed9ae7c582ce3db65f Mon Sep 17 00:00:00 2001 From: Ethan Resnick Date: Mon, 22 Oct 2018 17:23:52 -0400 Subject: [PATCH 2/8] feat(ux): add one extra level of outline headings This makes the sidebar table of contents more useful imo (for us and, soon, in user-defined profiles). --- _format/1.1/index.md | 8 ++++---- javascripts/all.js | 13 ++++++++----- stylesheets/all.css | 10 +++++----- stylesheets/all.sass | 6 +++--- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/_format/1.1/index.md b/_format/1.1/index.md index 9e1a3136b..b28eecd26 100644 --- a/_format/1.1/index.md +++ b/_format/1.1/index.md @@ -234,7 +234,7 @@ other and with `type` and `id`. In other words, a resource can not have an attribute and relationship with the same name, nor can it have an attribute or relationship named `type` or `id`. -#### Attributes +##### Attributes The value of the `attributes` key **MUST** be an object (an "attributes object"). Members of the attributes object ("attributes") represent information @@ -253,7 +253,7 @@ alongside other information to be represented in a resource object, these keys > Note: See [fields] and [member names] for more restrictions on this container. -#### Relationships +##### Relationships The value of the `relationships` key **MUST** be an object (a "relationships object"). Members of the relationships object ("relationships") represent @@ -285,7 +285,7 @@ data, not the related resources. > Note: See [fields] and [member names] for more restrictions on this container. -#### Related Resource Links +##### Related Resource Links A "related resource link" provides access to [resource objects][resource objects] [linked][links] in a [relationship][relationships]. When fetched, the related resource object(s) @@ -300,7 +300,7 @@ relationship isn't currently associated with any target resources. Additionally, a related resource link **MUST NOT** change because its relationship's content changes. -#### Resource Linkage +##### Resource Linkage Resource linkage in a [compound document] allows a client to link together all of the included [resource objects] without having to `GET` any URLs via [links]. diff --git a/javascripts/all.js b/javascripts/all.js index 4a4ca3277..44fe7f6a4 100644 --- a/javascripts/all.js +++ b/javascripts/all.js @@ -12,7 +12,6 @@ $(document).ready(function() { // Sidebar scroll affix fixElement($(".sidebar"), $("footer"), 52); - activateVersionPicker(); }); @@ -89,6 +88,14 @@ function createOutlineFromElement(element) { children: [] }; + $(this).nextUntil('h3', 'h4').each(function() { + childItem.children.push({ + title: $(this).not('a').text(), + href: $(this).find('a').attr('href') || "#", + children: [] + }); + }); + item.children.push(childItem); }); @@ -98,10 +105,6 @@ function createOutlineFromElement(element) { return outline; } -/** - * Creates a nested list from an array in the form returned by `createOutlineFromElement`. - */ - /** * Creates a nested list from an array in the form returned by `createOutlineFromElement`. * diff --git a/stylesheets/all.css b/stylesheets/all.css index 833eb002d..de0017289 100644 --- a/stylesheets/all.css +++ b/stylesheets/all.css @@ -304,21 +304,21 @@ footer { margin-bottom: 50px; } .sidebar { - width: 220px; + width: 235px; margin-top: 8px; float: left; } .sidebar h1 { font-size: 15px; background-color: white; z-index: 1; - width: 220px; + width: 235px; color: inherit; font-weight: 300; } .sidebar nav > ol { - width: 220px; + width: 235px; overflow-y: auto; } .sidebar #version-picker-wrapper { - width: 220px; + width: 200px; margin-bottom: 20px; display: flex; flex-direction: row; } @@ -343,7 +343,7 @@ footer { @media screen and (min-width: 886px) { .sidebar + .content { - margin-left: 235px; + margin-left: 245px; padding-left: calc(100vw - 886px); } } @media screen and (min-width: 901px) { .sidebar + .content { diff --git a/stylesheets/all.sass b/stylesheets/all.sass index 1007217c0..54a46a2f5 100644 --- a/stylesheets/all.sass +++ b/stylesheets/all.sass @@ -6,7 +6,7 @@ /** Config */ $page-width: 955px -$sidebar-width: 220px +$sidebar-width: 235px $page-padding: 20px $mobile-breakpoint: 800px @@ -307,7 +307,7 @@ footer overflow-y: auto #version-picker-wrapper - width: $sidebar-width + width: 200px margin-bottom: 20px display: flex flex-direction: row @@ -347,7 +347,7 @@ footer // just jump to its final size at the next media query. @media screen and (min-width: $page-width + ($page-padding * 2) - 109px) .sidebar + .content - margin-left: $sidebar-width + 15px + margin-left: $sidebar-width + 10px padding-left: calc(100vw - #{$page-width + ($page-padding * 2) - 109px}) @media screen and (min-width: $page-width + ($page-padding * 2) - 94px) From 6f620fa14a78ad2303936db1aee5268568f3aac8 Mon Sep 17 00:00:00 2001 From: Ethan Resnick Date: Mon, 22 Oct 2018 17:29:59 -0400 Subject: [PATCH 3/8] docs: add profile registration template, site pages, example profile --- _config.yml | 32 +- _format/1.1/index.md | 5 + _includes/global_head_assets.html | 32 + _includes/global_html_footer.html | 23 + _includes/header_offset_2.md | 33 + _includes/profile_url.md | 5 + _includes/site_navigation.html | 13 + _layouts/page.html | 83 +-- _layouts/profile.html | 71 ++ _layouts/profile_error.html | 28 + .../ethanresnick/cursor-pagination/index.md | 610 ++++++++++++++++++ .../cursor-pagination/max-size-exceeded.md | 3 + .../range-pagination-not-supported.md | 3 + .../cursor-pagination/unsupported-sort.md | 3 + extensions/index.md | 114 +++- index.md | 7 +- javascripts/all.js | 11 + profile_template | 54 ++ stylesheets/all.css | 42 +- stylesheets/all.css.map | 2 +- stylesheets/all.sass | 51 +- 21 files changed, 1127 insertions(+), 98 deletions(-) create mode 100644 _includes/global_head_assets.html create mode 100644 _includes/global_html_footer.html create mode 100644 _includes/header_offset_2.md create mode 100644 _includes/profile_url.md create mode 100644 _includes/site_navigation.html create mode 100644 _layouts/profile.html create mode 100644 _layouts/profile_error.html create mode 100644 _profiles/ethanresnick/cursor-pagination/index.md create mode 100644 _profiles/ethanresnick/cursor-pagination/max-size-exceeded.md create mode 100644 _profiles/ethanresnick/cursor-pagination/range-pagination-not-supported.md create mode 100644 _profiles/ethanresnick/cursor-pagination/unsupported-sort.md create mode 100644 profile_template diff --git a/_config.yml b/_config.yml index 795ecc305..771a57edc 100644 --- a/_config.yml +++ b/_config.yml @@ -13,11 +13,11 @@ whitelist: - jekyll-sitemap - jekyll-feed - jekyll-seo-tag - - jekyll-gist - jemoji incremental: false gist: noscript: false + # customize github pages quiet: false markdown: kramdown @@ -25,7 +25,9 @@ highlighter: rouge kramdown: input: GFM hard_wrap: false - auto_ids: false + auto_ids: true + auto_id_prefix: auto-id- + auto_id_stripping: true template: '' # cannot customize math_engine: mathjax # cannot customize syntax_highligher: rouge # cannot customize @@ -48,6 +50,9 @@ port: 9876 collections: format: output: true + profiles: + output: true + permalink: /:collection/:path defaults: - scope: @@ -57,6 +62,20 @@ defaults: layout: page show_sidebar: true is_spec_page: true + - scope: + path: "" + type: "profiles" + values: + layout: profile_error + is_spec_page: false + show_sidebar: false + - scope: + path: "*/*/*/index.md" + type: "profiles" + values: + layout: profile + is_spec_page: false + show_sidebar: true latest_version: 1.0 excerpt_separator: "" @@ -84,3 +103,12 @@ quicklinks: url: /format/ - title: Contribute on GitHub url: https://github.com/json-api/json-api + +profile_categories: + - Pagination + # these are some other potential categories. + # Uncomment them if you're adding a profile in one of these categories. + # - Filtering + # - Actions/Hypermedia + # - Data Modeling + # - Deep Querying diff --git a/_format/1.1/index.md b/_format/1.1/index.md index b28eecd26..f5c10b9c7 100644 --- a/_format/1.1/index.md +++ b/_format/1.1/index.md @@ -2222,6 +2222,11 @@ supported as well. 3. alter the JSON structure of any concept defined in this specification, including to allow a superset of JSON structures. + +> If you create your own profile, you are **strongly encouraged to [register](/extensions/#profile-registration) +> it** with the JSON API [profile registry](/extensions/), so that others can +> find and reuse it. + #### Revising a Profile Profiles **MAY** be revised over time, e.g., to add new capabilities. However, diff --git a/_includes/global_head_assets.html b/_includes/global_head_assets.html new file mode 100644 index 000000000..22551095d --- /dev/null +++ b/_includes/global_head_assets.html @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/global_html_footer.html b/_includes/global_html_footer.html new file mode 100644 index 000000000..78938024e --- /dev/null +++ b/_includes/global_html_footer.html @@ -0,0 +1,23 @@ + + diff --git a/_includes/header_offset_2.md b/_includes/header_offset_2.md new file mode 100644 index 000000000..221a039f5 --- /dev/null +++ b/_includes/header_offset_2.md @@ -0,0 +1,33 @@ +{% comment %} + When we embed the markdown from a user-provided profile specification + inside the profile layout, we need to increment each heading level by 2. + Kramdown, our markdown parser, provides a `header_offset` option, but + Jekyll only allows us to set that globally -- and setting it globally + to two would break our other pages. So, this include lets us take arbitrary + HTML (from rendered markdown) and does some liquid string replacements + to offset its headings. This is pretty janky (even more so because liquid + only allows us to do literal string replacement, not regex replacement), + but I think it *should* work robustly, thanks to the fact that angle + brackets (i.e., `<` and `>`) aren't supposed to appear in HTML unencoded, + and I imagine Kramdown respects that. +{% endcomment %} +{{ include.content + | replace: "", "" + | replace: "", "" + | replace: "", "" + | replace: "", "" + | replace: "", "" + | replace: "", "" + | replace: "", "" + | replace: "", "" + | replace: "", "" +}} diff --git a/_includes/profile_url.md b/_includes/profile_url.md new file mode 100644 index 000000000..7c66cde28 --- /dev/null +++ b/_includes/profile_url.md @@ -0,0 +1,5 @@ +{% comment %} + Takes the page object for a JSON:API profile spec and returns its url. + This file can't have whitespace outside this comment block or else the + output will be corrupted. +{% endcomment %}{{ include.page.url | absolute_url | split: "/" | where_exp: "item", "item != 'index'" | join: "/" }}/ \ No newline at end of file diff --git a/_includes/site_navigation.html b/_includes/site_navigation.html new file mode 100644 index 000000000..6ef5c513b --- /dev/null +++ b/_includes/site_navigation.html @@ -0,0 +1,13 @@ + diff --git a/_layouts/page.html b/_layouts/page.html index 063c5503c..b70fbb076 100644 --- a/_layouts/page.html +++ b/_layouts/page.html @@ -1,9 +1,7 @@ - - - + {% include global_head_assets.html %} {% comment %} Below, we're either dealing with a generic page or a page from the @@ -20,57 +18,15 @@ {% else %} {% assign page_title = page.title %} {% endif %} - JSON API — {{page_title|strip }} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + JSON API — {{ page_title|strip }} - + {% include site_navigation.html %} {% if page.show_masthead %}
-

JSON API

+

JSON API

A specification for building APIs in JSON

{% endif %} -
+
{% unless page.show_masthead %}

{{ page_title }} @@ -136,31 +93,9 @@

{% endif %} {{ content }} -

+
- - + {% include global_html_footer.html %} diff --git a/_layouts/profile.html b/_layouts/profile.html new file mode 100644 index 000000000..8ab61bb8a --- /dev/null +++ b/_layouts/profile.html @@ -0,0 +1,71 @@ + + + + {% include global_head_assets.html %} + {% capture page_title %}“{{ page.name | smartify }}” Profile{% endcapture %} + JSON API — {{ page_title|strip }} + + + + {% include site_navigation.html %} +
+ +
+

+ {{ page_title }} +

+
+

Introduction

+

This is the specification of a profile for the JSON:API specification.

+

The url for this profile is {% include profile_url.md page=page %}.

+ + {% capture extended_description_markdown %} + {{ page.extended_description | markdownify }} + {% endcapture %} + {% include header_offset_2.md content=extended_description_markdown %} +
+ {% if page.minimum_jsonapi_version > 1.0 %} +
+

+ + Minimum JSON:API Version +

+ +

This profile requires at least JSON:API version {{ page.minimum_jsonapi_version }}.

+ {% capture minimum_version_markdown %} + {{ page.minimum_jsonapi_version_explanation | markdownify }} + {% endcapture %} + {% include header_offset_2.md content=minimum_version_markdown %} +
+ {% endif %} +
+

Specification

+ {% include header_offset_2.md content=content %} +
+
+

Contact the Author

+ {% if page.discussion_url %} +

To discuss or ask questions about this extension, visit + {{ page.discussion_url }}.

+

You can also contact the author directly:

+ {% endif %} +
+ {{ page.author_name }}
+ {{ page.author_email }}
+ {% if page.author_website %} + {{ page.author_website }}
+ {% endif %} + {% if page.author_phone %} + {{ page.author_phone }}
+ {% endif %} +
+
+
+
+ {% include global_html_footer.html %} + + diff --git a/_layouts/profile_error.html b/_layouts/profile_error.html new file mode 100644 index 000000000..cbe0ea42d --- /dev/null +++ b/_layouts/profile_error.html @@ -0,0 +1,28 @@ + + + + {% include global_head_assets.html %} + JSON API — {{ page.title|strip }} + + + + {% include site_navigation.html %} +
+ {% if page.show_sidebar %} + + {% endif %} +
+

{{ page.title }}

+
+ {{ content }} +
+
+
+ {% include global_html_footer.html %} + + + diff --git a/_profiles/ethanresnick/cursor-pagination/index.md b/_profiles/ethanresnick/cursor-pagination/index.md new file mode 100644 index 000000000..e11aa68bb --- /dev/null +++ b/_profiles/ethanresnick/cursor-pagination/index.md @@ -0,0 +1,610 @@ +--- +name: Cursor Pagination +short_description: | + Enables pagination forward and backwards from a client-provided cursor, with + a client-controlled page size. + +extended_description: | + Cursor-based pagination (aka keyset pagination) is a [common](https://slack.engineering/evolving-api-pagination-at-slack-1c1f644f8e12) + [pagination strategy](https://www.citusdata.com/blog/2016/03/30/five-ways-to-paginate/) + that avoids many of the pitfalls of "offset–limit" pagination. + + For example, with offset–limit pagination, if an item from a prior page is + deleted while the client is paginating, all subsequent results will be shifted + forward by one. Therefore, when the client requests the next page, there's one + result that it will skip over and never see. Conversely, if a result is added + to the list of results as the client is paginating, the client may see the + same result multiple times, on different pages. Cursor-based pagination + can prevent both of these possibilities. + + Cursor-based pagination also performs better for large data sets under most + implementations. + + To support cursor-based pagination, this specification defines three query + parameters — `page[size]`, `page[before]`, and `page[after]` —  + and a method for providing clients with pagination links and cursors in response + bodies. + + For example, this request would get the next 100 people after the cursor `abcde`: + + ``` + GET /people?page[size]=100&page[after]=abcde + ``` + + Replacing `page[after]` with `page[before]` would allow the client to paginate + backwards. + + Alternatively, to find all people between cursors `abcde` and `fghij` + (exclusive), the client could request: + + ``` + GET /people?page[after]=abcde&page[before]=fghij + ``` + + Other combinations are possible, and these parameters are described more below. + +# If your profile defines values that can only be used in document members that +# were introduced after JSON:API v1.0, change the minimum_jsonapi_version field +# and fill in the minimum_jsonapi_version_explanation field with an explanation +# of the features you're relying on from the JSON:API version you've indicated. +minimum_jsonapi_version: 1.0 +minimum_jsonapi_version_explanation: + +# Url of a Github repo or some other place where people can +# ask questions/start discussions about your extension. +discussion_url: http://tets.com + +author_name: Ethan Resnick +author_email: ethan.resnick@gmail.com +# Optional fields +author_website: https://ethanresnick.com/ +author_phone: +13104398032 # use `tel` url format. + +# Valid categories are listed under the profile_categories section +# in https://github.com/json-api/json-api/blob/gh-pages/_config.yml +categories: + - Pagination +--- +# Concepts + +## Sorting Requirement + +**Pagination only applies to an ordered list of results.** This order must not +change between requests unless the underlying data changes, to ensure that +results don't arbitrarily move between pages. + +If the client's paginated request includes a `?sort` query parameter that +only partially orders the results, the server **MUST** apply additional +sorting constraints — consistent with the client-requested ones — to produce +a unique ordering, if it wishes to support pagination of that data. + +For example, suppose a client requests `GET /people?sort=age&page[size]=10`. +If multiple people have the same age, their relative ordering is not defined +(and could vary between requests), making pagination impossible. Therefore, +to fulfill the request, the server must treat all paginated requests with +`?sort=age` as though the client had instead asked to sort by age followed +by some unique field or combination of fields (e.g., `?sort=age,id`). + +Similarly, when the collection being paginated has no natural or +client-requested order (like the set of resource identifier objects in +a relationship), the server **MUST** assign an order if it wishes to support +pagination. + +The server **MAY** reject pagination requests if the client has requested that +the results be sorted in a way that server cannot efficiently paginate. In that +case, the server **MUST** reject the request according to the rules for the +[unsupported sort error]. + +## Cursors +A "cursor" is a string, created by the server using whatever method it likes, +that divides the list of results into those that fall before the cursor, those +that fall after the cursor, and, optionally, one result that falls "on" the +cursor. + +For example, imagine that the list of results being paginated is as follows: + +``` +[ + { "type": "examples", "id": "1" }, + { "type": "examples", "id": "5" }, + { "type": "examples", "id": "7" }, + { "type": "examples", "id": "8" }, + { "type": "examples", "id": "9" } +] +``` + +For this list, the server might produce the cursor string `abcde` as its way of +encoding "id = 5". With that cursor, then, the first result would fall before +the cursor, the second result would fall on the cursor, and the other results +would fall after it. + +The list of results **MAY** change between the client's pagination requests. +For example, the result with `"id": "5"` might be removed from the result set if +the resource it refers to is deleted. In that case, the cursor `abcde` would no +longer fall on any one result, but the same results would still come before it +and after it. + +In rare cases, a server may find it unacceptable for the results list to change +between a client's pagination requests. In those cases, the server **MAY** +encode into the cursor information uniquely identifying the client or its session, +and use that identifier to return consistent results from a single "snapshot" in +time. + +# Query Parameters + +## `page[size]` + +The ```page[size]``` parameter indicates the number of results that the client +would like to see in the response. + +If `page[size]` is provided, it **MUST** be a positive integer.[1](#fn-1) +If this requirement isn't met — e.g. if `page[size]` is negative — the server +**MUST** respond according to the rules for the [invalid query parameter error]. + +For each endpoint on which it supports pagintation, a server **MAY** define a +maximum number of results that it will send in response to a paginated request +to that endpoint. This is called the "max page size". If the server does not +choose a max page size for a given endpoint, it is implicitly infinity. + +If `page[size]` exceeds the server-defined max page size, the server **MUST** +respond according to the rules for the [max page size exceeded error]. + +If `page[size]` is omitted, the server **MUST** choose a "default page size". +This default size **MUST** be an integer between 1 and the max page size, +inclusive. + +The `page[size]` value, or the default page +size if `page[size]` is omitted, is called the "used page size". + +On any valid paginated request, the number of [pagination items][pagination item] +returned **MUST** equal the used page size — provided there are at +least that many items in the results list, and which satisfy the constraints of +the `page[after]` and/or `page[before]` parameters (if any). + +## `page[after]` and `page[before]` + +The `page[after]` and `page[before]` parameters are both optional and both, if +provided, take a cursor as their value. If their value is not a valid cursor, +the server **MUST** respond according to the rules for the +[invalid query parameter error]. + +The `page[after]` parameter is typically sent by the client to get the next page, +while `page[before]` is used to get the prior page. + +More formally, when `page[after]` is provided, the returned [paginated data] +**MUST** have as its first item the item that is *immediately after* the cursor +in the results list. (An exception is that, if there are no items in the results +list that fall after the cursor, the returned paginated data **MUST** be an +empty array.) + +When `page[before]` is provided, the *last* item returned in the [paginated data] +**MUST** be the item that is closest to, but still before, the cursor in the +unpaginated results list. (Analogous to the above, if there are no items in the +results list that fall before the cursor, the returned paginated data **MUST** +be an empty array.) + +For example, imagine that the list of results being paginated is again: + +``` +[ + { "type": "examples", "id": "1" }, + { "type": "examples", "id": "5" }, + { "type": "examples", "id": "7" }, + { "type": "examples", "id": "8" }, + { "type": "examples", "id": "9" } +] +``` + +Further, imagine that the cursor `xxx` falls on the entry with `"id": "9"`, +while the cursor `abcde` still falls on the entry with `"id": "5"`. + +Then, for example, if the request was: + +``` +GET /example-data?page[after]=abcde&page[size]=2 +``` + +The response would contain: + +``` +{ + "links": { + "prev": "/example-data?page[before]=yyy&page[size]=2", + "next": "/example-data?page[after]=zzz&page[size]=2" + }, + "data": [ + // the pagination item metadata is optional below. + { "type": "examples", "id": "7", "meta": { "page": { "cursor": "yyy" } } }, + { "type": "examples", "id": "8", "meta": { "page": { "cursor": "zzz" } } } + ] +} +``` + +Alternatively, if the request was: + +``` +GET /example-data?page[before]=xxx&page[size]=3 +``` + +The response would contain: + +``` +{ + "links": { + "prev": "/example-data?page[before]=abcde&page[size]=3" + "next": "/example-data?page[after]=zzz&page[size]=3" + }, + "data": [ + // again, optional pagination item metadata is allowed for each item here. + { "type": "examples", "id": "5" }, + { "type": "examples", "id": "7" }, + { "type": "examples", "id": "8" } + ] +} +``` + +Notice that the `page[before]=xxx` is causing the last item in the response's +[paginated data] to be the entry with `"id": "8"`, while the number of items in +the paginated data above that item is controlled by the used page size. + +### Omitting Both `page[after]` and `page[before]` +If the client's paginated request includes neither the `page[after]` nor the +`page[before]` parameters, the returned [paginated data] **MUST** start with +the first item from the results list. (If the results list is empty, the +paginated data **MUST** be an empty array.) + +### Combining `page[after]` and `page[before]` +Clients **MAY** use the `page[after]` and `page[before]` parameters together on +the same request. These are called "range pagination requests", as the client is +asking for all the results starting from immediately after the `page[after]` +cursor and continuing up until the `page[before]` cursor. + +Servers are not required to support such requests. If the server chooses not to +support these requests, it **MUST** respond according to the rules for the +[range pagination not supported error]. + +On range pagination requests, the server **MUST** use its max page size for that +endpoint as the default page size. In other words, the [used page size] will +either by the value of the `page[size]` parameter or the max page size. + +If the number of results that satisfy both the `page[after]` and `page[before]` +constraints exceeds the used page size, the server **MUST** respond with the +same [paginated data] that it would have if the `page[before]` parameter had not +been provided. However, in this case the server **MUST** also add +`"rangeTruncated": true` to the [pagination metadata] to indicate to the client +that the paginated data does not contain all the results it requested. + +For example, given our example data and cursors above, imagine the client +requests: + +``` +GET /example-data?page[after]=abcde&page[before]=xxx +``` + +Then, assuming our server's max page size was greater than 1, the response +would contain: + +``` +{ + "links": { + "prev": "/example-data?page[before]=yyy", + "next": "/example-data?page[after]=zzz" + }, + "data": [ + { "type": "examples", "id": "7" }, + { "type": "examples", "id": "8" } + ] +} +``` + +However, if our server's max page size was 1, or the client included +`page[size]=1` in its request, the response would contain: + +``` +{ + "meta": { + "page": { "rangeTruncated": true } + }, + "links": { + "prev": "/example-data?page[before]=yyy&page[size]=1", + "next": "/example-data?page[after]=yyy&page[size]=1" + }, + "data": [ + { "type": "examples", "id": "7" } + ] +} +``` + +# Document Structure + +## Terms +This profile uses the following terms to refer to different document elements: + +1. paginated data: an array in a JSON:API + response document that holds the results that were extracted from a full list + of results being paginated. It is always the value of a `data` key. When the + [primary data](https://jsonapi.org/format/#document-top-level) is being + paginated, the value of the document's top-level `data` key is paginated data. + When the resource identifier objects in a relationship are being paginated, + the value of the `data` key in the relationship object is paginated data. + +2. pagination links: the `links` object + that's a sibling of the paginated data. + +3. pagination metadata: the [`page` + member] of the `meta` object that's a sibling of the paginated data (and + pagination links). + +4. pagination item: an entry in the + paginated data array. + +5. pagination item metadata: the + [`page` member] of the `meta` object that's at the top-level of a + paginated data item. + +To demonstrate these terms, various elements are labeled in the following +example: + +``` +GET /people?page[size]=1 +``` +``` +{ + // "pagination links" (for the top-level `data`) + "links": { }, + "meta": { + // "pagination metadata" + "page": {} + }, + // "paginated data" + "data": [ + // a "pagination item" + { + "type": "people", + "id": "1", + // "pagination item metadata" in `page`. + "meta": { "page": {} }, + "attributes": {}, + "relationships": { + "friends": { + // "pagination links". + // would be non-empty in practice to indicate that the server + // has chosen to paginate this relationship, even though the + // client hasn't explicitly asked, which is allowed. + "links": {}, + // another instance of "paginated data" + "data": [ + // a "pagination item", with (empty) "pagination item metadata". + { "type": "people", "id": "3", "meta": { "page": { } } } + ] + } + } + } + ] +} +``` + +## `page` Meta Object Members +This profile reserves a `page` member in every JSON:API-defined `meta` object. +(Each of these `page` members constitutes an element defined by this profile, +so they can be [aliased](https://jsonapi.org/format/1.1/#profile-keywords-and-aliases).) + +The `page` member, when present, **MUST** hold an object as its value; any other +values are [unrecognized](https://jsonapi.org/format/1.1/#profiles-processing). +The recognized keys/values in these various `page` objects are defined throughout +this specification. + + +## Item Cursors +The server **MAY** choose to send some or all pagination items back to the client +with a `cursor` member in the [pagination item's metadata][pagination item metadata]. +If present, this member **MUST** hold a cursor that (at the time of the response) +["falls on"][cursor] the item it is returned with. Clients can use this cursor +to paginate from this item. + +For example, a response might contain: + +``` +{ + // top-level links, meta, etc. omitted. + // more people would likely be in the response as well. + "data": [{ + "type": "people", + "id": "3", + "meta": { + "page": { "cursor": "someOpaqueString" } + } + //... + }] +} +``` + +With this response, clients could use `page[before]=someOpaqueString` or +`page[after]=someOpaqueString` to paginate from person 3 in either direction. + +## Links +JSON:API allows four types of pagination links: [`prev`, `next`, `first`, and +`last`](https://jsonapi.org/format/#fetching-pagination). + +It is **RECOMMENDED** that servers include `first` and `last` links when these +are inexpensive to compute. + +However, servers **MUST** include a `prev` and a `next` link for each instance +of paginated data in a response. + +If a request does not contain the `page[before]` parameter, the server **MUST** +determine whether a next page exists, and return `null` as the `next` link if not. + +If a request does not contain the `page[after]` parameter, the server **MUST** +determine whether a previous page exists, and return `null` as the `prev` link +if not. + +In all other cases, a server **SHOULD** set these links to `null` when it can +inexpensively determine that the current response is for the first or last page +respectively. + +However, if the server can't easily determine whether there are prior results +(when computing the `prev` link) or subsequent results (when computing the +`next` link), it **MAY** use a URI in these links that returns an empty array +as its paginated data. + +For example, imagine a request for: + +``` +GET /example-data?page[before]=xyz +``` + +To fulfill this request, the server will likely issue a query that filters the +full `example-data` results list to find only records that are before the cursor. +From those query results, the server would not know whether there are additional +results that come *after* the cursor, and it may not have a cheap way to find out. + +So, in this case, the server can simply return a `next` URI where the `page[after]` +parameter is set to the [item cursor][item cursors] for the last item in the +response's paginated data. + +If the client goes to fetch this link, it will either receive an empty array +as the paginated data, in which case it knows it's reached the end, or it will +get the subsequent results. + +> Note: in general, servers are likely to find it more expensive to determine +whether a previous page exists when `page[after]` is in use, and whether a +subsequent page exists when `page[before]` is in use. Luckily, when `page[after]` +is in use, clients usually don't care about the previous page (only the next +one), and vice-versa when `page[before]` is in use. So, by allowing the server +to return a link that might end up corresponding to an empty page, the server +can often skip a query that will never be needed. + +## Collection Sizes +The pagination metadata **MAY** contain a `total` member containing an integer +indicating the total number of items in the list of results that's being +paginated. + +For example, a response to `GET /people?page[size]=2` might include: + +``` +{ + "meta": { + "page": { "total": 200 } + }, + // links omitted + "data": [ + { + "type": "people", + // ... + }, + { + "type": "people", + // ... + } + ] +} +``` + +The pagination metadata **MAY** also contain an `estimatedTotal` member. +If present, the value of this member **MUST** be an object. That object +**MAY** have one key, `bestGuess`. If present, `bestGuess` **MUST** contain +an integer indicating the server's best estimate of the size of the full results +list. + +Server's might choose to use `estimatedTotal` instead of `total` when computing +the exact total is costly. + +# Error Cases +## Unsupported Sort Error +The server **MUST** respond to this error by sending a `400 Bad Request`. The +response document **MUST** contain an error object that identifies the `sort` +parameter as the [error's `source`](https://jsonapi.org/format/#error-objects), +and has a `type` link of: + +``` +https://jsonapi.org/profiles/ethanresnick/cursor-pagination/unsupported-sort +``` + + +## Max Page Size Exceeded Error +The server **MUST** respond to this error by sending a `400 Bad Request`. The +response document **MUST** contain an error object that: + +- identifies `page[size]` as the error's `source`; +- provides the maximum page size as an integer in `maxSize` member of the `page` + element in the error object's `meta` object; and +- includes a `type` link of: + + ``` + https://jsonapi.org/profiles/ethanresnick/cursor-pagination/max-size-exceeded + ``` + +If this profile's `page` element has not been [aliased](https://jsonapi.org/format/1.1/#profile-keywords-and-aliases), +the error object might look like: + +``` +{ + "status": "400", + "meta": { + "page": { "maxSize": 100 } + }, + "title": "Page size requested is too large.", + "detail": "You requested a size of 200, but 100 is the maximum.", + "source": { + "parameter": "page[size]" + }, + "links": { + "type": ["https://jsonapi.org/profiles/ethanresnick/cursor-pagination/max-size-exceeded"] + } +} +``` + +## Invalid Parameter Value Error +The server **MUST** respond to this error by sending a `400 Bad Request` with an +error object in the response document that identifies the problematic parameter +in the error object's `source` member. + +For example, the server might send: + +``` +{ + "errors": [{ + "title": "Invalid Parameter.", + "detail": "page[size] must be a positive integer; got 0", + "source": { "parameter": "page[size]" }, + "status": "400" + }] +} +``` + +## Range Pagination Not Supported Error +The server **MUST** respond to this error by sending a `400 Bad Request`. The +response document **MUST** contain an error object that has a `type` link of: + +``` +https://jsonapi.org/profiles/ethanresnick/cursor-pagination/range-pagination-not-supported +``` + +# Notes + +1. Technically, a URI is a series of characters, so the value + of a query parameter -- including `page[size]` -- is always a string. When + the text says the value "MUST be a positive integer", it means more precisely + that the value **MUST** be a sequence of characters matching the regular + expression `^[0-9]+$`, which **MUST** then be interpreted as a base-10 integer. + + +[sorting requirement]: #concepts-sorting +[cursor]: #concepts-cursors + +[`page` member]: #document-page-meta +[item cursors]: #document-item-cursors + +[range pagination]: #query-range-pagination + +[used page size]: #terms-used-page-size +[paginated data]: #terms-paginated-data +[pagination metadata]: #terms-pagination-metadata +[pagination item]: #terms-pagination-item +[pagination item metadata]: #terms-pagination-item-metadata + +[unsupported sort error]: #errors-unsupported-sort +[max page size exceeded error]: #errors-max-page-size-exceeded +[invalid query parameter error]: #errors-invalid-query-parameter +[range pagination not supported error]: #errors-range-pagination-not-supported diff --git a/_profiles/ethanresnick/cursor-pagination/max-size-exceeded.md b/_profiles/ethanresnick/cursor-pagination/max-size-exceeded.md new file mode 100644 index 000000000..b7a9f9267 --- /dev/null +++ b/_profiles/ethanresnick/cursor-pagination/max-size-exceeded.md @@ -0,0 +1,3 @@ +--- +redirect_to: /profiles/ethanresnick/cursor-pagination/#auto-id-pagesize +--- diff --git a/_profiles/ethanresnick/cursor-pagination/range-pagination-not-supported.md b/_profiles/ethanresnick/cursor-pagination/range-pagination-not-supported.md new file mode 100644 index 000000000..21d10b38e --- /dev/null +++ b/_profiles/ethanresnick/cursor-pagination/range-pagination-not-supported.md @@ -0,0 +1,3 @@ +--- +redirect_to: /profiles/ethanresnick/cursor-pagination/#query-range-pagination +--- diff --git a/_profiles/ethanresnick/cursor-pagination/unsupported-sort.md b/_profiles/ethanresnick/cursor-pagination/unsupported-sort.md new file mode 100644 index 000000000..1507442a1 --- /dev/null +++ b/_profiles/ethanresnick/cursor-pagination/unsupported-sort.md @@ -0,0 +1,3 @@ +--- +redirect_to: /profiles/ethanresnick/cursor-pagination/#concepts-sorting +--- diff --git a/extensions/index.md b/extensions/index.md index 198060ca6..b7b8b771c 100644 --- a/extensions/index.md +++ b/extensions/index.md @@ -2,22 +2,118 @@ layout: page title: Extensions show_sidebar: true +redirect_from: /profiles --- -## Status +JSON:API can be extended with profiles. These profiles enable an API to +provide clients with information or functionality beyond that described +in the base JSON:API specification. -**An extension system is currently under development,** and you can view the -latest work [here](https://github.com/json-api/json-api/tree/profile-extensions). -There is no official support for extensions in the base JSON API specification. +Anyone can author a profile, and a single profile can be reused by multiple APIs. +Popular profiles may be implemented by off-the-shelf tools so that developers +can seamlessly take advantage of the features these profiles provide. + +## Existing Profiles + +{% for category in site.profile_categories %} +

+ {{ category }} +

+
+ {% for profile in site.profiles %} + {% if profile.categories contains category %} +
{{ profile.name }}
+
{{ profile.short_description }}
+ {% endif %} + {% endfor %} +
+{% endfor %} + +## Creating a New Profile + +### Before Creating a Profile + +Please **check whether an existing profile fits your needs or could be amended +to fit your needs** before developing a new one. + +- If a suitable profile already exists, consider using it. Having fewer, more +widely-deployed profiles makes it easier to create shared tooling. + +- If there's an existing profile that could be amended to fit your needs, +consider asking the profile's author if they would be willing to modify it as +needed. Contact them through the information in their profile's registration +and give them some time to reply. + +### Authoring Your Profile + +To author your profile, [download and fill out the template](/profile_template.md). + +### Register & Use Your Profile + +Once you've authored your profile, submit it to the JSON:API profile registry. +By registering your profile: + +1. it will be listed above for others to find and reuse. + +2. it will be given an official url on jsonapi.org. This will be the URL you and + others use to apply/identify the profile. + +3. one of the JSON API's editors will review your submission to check that it + follows the [profile extension requirements](/format/1.1/#profiles-authoring). + These requirements can be a bit tricky, so getting an expert review ensures + that your profile is legal for use with JSON:API. + +To register your profile: + +1. Choose a namespace, which is a name that uniquely identifies you or your + organization. (All profiles authored by the same person or organization are + registered under the same namespace, to prevent naming conflicts.) This + namespace should be your Github username, or the name of a Github organization + to which you belong. In unusual circumstances, you can request to use a + different name as the namespace in your PR (see below). + +2. Create a PR to [the json-api repository](https://github.com/json-api/json-api). + In the PR, make a directory at `_profiles/{NAMESPACE}/{PROFILE_NAME}` (where + `PROFILE_NAME` is the name of your profile, dasherized), and put your filled + out template as the `index.md` file in that directory folder. (See [an example](https://github.com/json-api/json-api/tree/1.1/_profiles/ethanresnick/cursor-pagination).) + +Once submitted, one of JSON:API's editors will review your profile to check that +it: 1) follows the template above; 2) complies with JSON:API's [requirements for profiles](/format/1.1/#profiles-authoring); +and 3) wouldn't cause any problems were it to become widely adopted. If your +profile meets these three criteria, it will generally be **approved within a week**. + +In limited cases (e.g., if your profile defines a new, fundamental mechanism for +doing something "architectural" that other profiles may need to do too), it might +take longer for the reviewer to adequately check that the profile wouldn't have +problematic ramifications if it became widely adopted. + +As part of this review, the editors or the community might also give design +feedback on your submission. You can take as much time as you'd like to act on/ +respond to this feedback, and the editors will wait for you to say that your +submission is finalized before merging your PR. You are encouraged, but not +required, to act on any design feedback. + +If you do change your submission after it's been reviewed, it will be re-reviewed +to make sure it still complies with the requirements for approval given above. + +JSON:API's editors may occasionally reassign responsibility for a registered +profile. The most common case of this will be to enable changes to be made to +profiles where the author of the registration has died, moved out of contact or +is otherwise unable to make changes that are important to the community. + +Even though profile registration is strongly encouraged, it is not mandatory. +If you choose not to register your profile, you can create your own URL, on +a domain you control, and use that to identify your profile. You should +self-host the filled out template at this URL. ## Prior Extensions JSON API previously offered experimental support for a different extension -negotiation system than the one now being discussed, and it provided a number of -extensions for use with that old negotiation system. However, this system was -always experimental and has now been deprecated. +negotiation system than the one now in the specification, and it provided a +number of extensions for use with that old negotiation system. However, this +system was always experimental and has now been deprecated. -New APIs should not use the old system or any extensions designed for it. APIs -that already use these old extensions should direct clients to an +New APIs should not use the old system or any extensions designed for it. +APIs that already use these old extensions should direct clients to an [earlier version of this page](https://github.com/json-api/json-api/blob/9c7a03dbc37f80f6ca81b16d444c960e96dd7a57/extensions/index.md) as documentation. diff --git a/index.md b/index.md index 786f81553..620ccf163 100644 --- a/index.md +++ b/index.md @@ -116,10 +116,11 @@ specification](/format). ## Extensions -JSON API has [experimental support for extensions](/extensions). +The JSON API community has created a collection of extensions that APIs can use +to provide clients with information or functionality beyond that described in the base JSON API specification. These extensions are called profiles. -Official extensions are being developed for [Bulk](/extensions/bulk/) and -[JSON Patch](/extensions/jsonpatch/) operations. +You can [browse existing profiles](/extensions/#existing-profiles) or +[create a new one](/extensions/#profile-creation). ## Update history diff --git a/javascripts/all.js b/javascripts/all.js index 44fe7f6a4..d030f35af 100644 --- a/javascripts/all.js +++ b/javascripts/all.js @@ -1,6 +1,17 @@ //= require_tree . $(document).ready(function() { + // Add links within headings from user-provided profiles markup for + // easy jumping and so outline generation works. + $('h2, h3, h4, h5', document.querySelector('#profile-spec-container')).each(function() { + var $this = $(this); + + if($this.find("a.headerlink").length === 0 && $this.attr('id')) { + $this.prepend(''); + } + }); + + // Build navigation list var documentOutlineElement = $("#document-outline"); diff --git a/profile_template b/profile_template new file mode 100644 index 000000000..610688975 --- /dev/null +++ b/profile_template @@ -0,0 +1,54 @@ +--- +permalink: /profile_template.md +--- +--- +name: Your Profile's Name +short_description: | + A short descriptions (1-3 sentences) about your profile's purpose and + features, to help others determine if it will work for them. + +extended_description: | + A description used in the introduction section on the profile's dedicated + page. This can be as long as you want, and can contain markdown. + +# If your profile defines values that can only be used in document members that +# were introduced after JSON:API v1.0, change the minimum_jsonapi_version field +# and fill in the minimum_jsonapi_version_explanation field with an explanation +# of the features you're relying on from the JSON:API version you've indicated. +minimum_jsonapi_version: 1.0 +minimum_jsonapi_version_explanation: + +# Url of a Github repo or some other place where people can +# ask questions/start discussions about your extension. +discussion_url: http://tets.com + +author_name: Ethan Resnick +author_email: ethan.resnick@gmail.com +# Optional fields +author_website: https://ethanresnick.com/ +author_phone: +13104398032 # use `tel` url format. + +# Valid categories are listed under the profile_categories section +# in https://github.com/json-api/json-api/blob/gh-pages/_config.yml +categories: + - Filtering +--- + +Here, specify your profile. This description should be detailed enough to allow +for interoperable implementations, but it otherwise doesn't need to be formal. +At the very least, describe the elements (document data or query parameters) +your profile defines and the allowed values for each. + +Make sure you __follow the authoring guidelines__, which describe what profiles +are and are not allowed to do, and how they should be designed to evolve over time. + +Those authoring guidelines are at: + http://jsonapi.org/format/1.1/#profiles-authoring + +Finally, it is **strongly encouraged** that your profile reuse objects, +patterns, and key names from the main JSON API specification where appropriate. + +For instance, if your profile defines a field that points to another JSON API +resource, that field should hold a resource identifier object. Or, if your +extension defines a "type" key, it should use that key as JSON API does +(i.e. to hold a string indicating a resource's type). diff --git a/stylesheets/all.css b/stylesheets/all.css index de0017289..fab5a3766 100644 --- a/stylesheets/all.css +++ b/stylesheets/all.css @@ -93,7 +93,7 @@ footer .site-wrapper, footer .social-links { text-transform: uppercase; letter-spacing: 0.2px; } -header h1, footer .social-links span { +header h1#json-api, footer .social-links span { text-indent: -119988px; overflow: hidden; text-align: left; @@ -134,7 +134,7 @@ h1 { color: #0b4e22; } h2 { - margin: 50px 0 15px 0; + margin: 2em 0 15px 0; color: #5a5a5a; font-size: 22px; line-height: 1.3; } @@ -165,13 +165,19 @@ th { a { color: #5a5a5a; } -blockquote { +blockquote, .note { margin: 20px 0; - padding: 10px 15px 0 15px; + padding: 10px 15px 10px 15px; border-radius: 4px; color: gray; background: rgba(90, 90, 90, 0.04); border: 1px solid #cccccc; } + blockquote code, .note code { + background: inherit !important; } + blockquote p, .note p { + margin-bottom: 6px; } + blockquote p:last-child, .note p:last-child { + margin-bottom: 0; } p > code, li > code { padding: 1px 4px; @@ -181,6 +187,9 @@ p > code, li > code { code { font-weight: inherit; } +address { + font-style: normal; } + /** Navigation */ .site-nav { font-weight: 500; @@ -226,7 +235,7 @@ header .content { padding: 29px 20px 41px; background: #ebebeb; border-bottom: 1px solid #cccccc; } -header h1 { +header h1#json-api { text-align: center; height: 130px; margin: 0; @@ -380,4 +389,27 @@ pre.highlight { margin: 2em 0; font-family: Menlo, monospace; } +/** Extensions page */ +.profiles-list dt, .profiles-list dd { + display: inline; + margin-left: 0; } +.profiles-list dd::after { + display: block; + content: " "; + height: 0.8em; } +.profiles-list dt::before { + content: "•"; + font-size: 1.56em; + margin-right: 1em; + position: absolute; + margin-left: -0.66em; + line-height: 1.1em; } + +/** Individual profile page */ +.profile-page h2 { + margin-top: 2em; } + +.profile-page h1 + section h2 { + margin-top: 1em; } + /*# sourceMappingURL=all.css.map */ diff --git a/stylesheets/all.css.map b/stylesheets/all.css.map index 07354ac35..b414463a8 100644 --- a/stylesheets/all.css.map +++ b/stylesheets/all.css.map @@ -1,6 +1,6 @@ { "version": 3, -"mappings": "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", +"mappings": ";AAAA,QAAS;EACP,OAAO,EAAE,KAAK;EAAE,OAAO,EAAE,KAAK;EAC9B,KAAK,EAAE,IAAI;;AAGb,uHAAU;EACR,KAAK,EAAE,OAAO;;AAGhB,+CAAY;EACV,KAAK,EAAE,IAAI;;AAIX,sBAAS;EACP,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,MAAM;;AAiBpB,qCAAkB;EAChB,WAAW,EAAE,IAAI;AAenB,sBAAa;EACX,KAAK,EAAE,IAAI;;AClDf,UASC;EARC,WAAW,EAAE,UAAU;EACvB,GAAG,EAAE,qCAAqC;EAC1C,GAAG,EAAE,sPAG4D;EACjE,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,MAAM;AAEpB,iGAAiG;AACjG,4FAA4F;AAC5F;;;;;;;EAOE;AAED,iDAAkD;EACjD,WAAW,EAAE,UAAU;EACvB,UAAU,EAAE,MAAM;EAClB,WAAW,EAAE,MAAM;EACnB,KAAK,EAAE,IAAI;EAEX,OAAO,EAAE,YAAY;EACrB,eAAe,EAAE,OAAO;EACxB,KAAK,EAAE,GAAG;EACV,UAAU,EAAE,MAAM;EAElB,iEAAiE;EACjE,YAAY,EAAE,MAAM;EACpB,cAAc,EAAE,IAAI;EAEpB,+CAA+C;EAC/C,WAAW,EAAE,GAAG;;AAGlB,mBAAoB;EAAE,OAAO,EAAE,OAAO;;AAAI,SAAS;AACnD,iBAAkB;EAAE,OAAO,EAAE,OAAO;;AAAI,SAAS;AACjD,mBAAoB;EAAE,OAAO,EAAE,OAAO;EAAE,SAAS,EAAE,IAAI;EAAE,QAAQ,EAAE,QAAQ;EAAE,GAAG,EAAE,KAAK;EAAE,IAAI,EAAE,KAAK;;AAAI,SAAS;AACjH,kBAAmB;EAAE,OAAO,EAAE,OAAO;;AAAI,SAAS;AAClD,oBAAqB;EAAE,OAAO,EAAE,OAAO;;AAAI,SAAS;;;ACnBpD,uDAAU;EACR,OAAO,EAAE,KAAK;EACd,SAAS,EApBE,KAAK;EAqBhB,MAAM,EAAE,MAAM;EACd,OAAO,EAAE,MAAe;;AAE1B,0CAAoB;EAClB,UAAU,EAAE,OAAO;EAEnB,sDAAO;IACL,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,YAAY;IACrB,KAAK,EAAE,IAAI;;AAEf,gCAAW;EACT,cAAc,EAAE,SAAS;EACzB,cAAc,EAAE,KAAI;;AAItB,6CAAU;ECMN,WAAW,EAAE,SAA8C;EAC3D,QAAQ,EAAE,MAAM;EAChB,UAAU,EAAE,IAAI;EAShB,cAAc,EAAC,UAAU;;ADd7B,gCAAa;EEkCH,OAAO,EAAE,YAAyB;EAAlC,OAAO,EAAE,IAAyB;;AF9B5C,IAAI;EACF,WAAW,EAlCA,6DAA6D;EAmCxE,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,GAAG;EAChB,sBAAsB,EAAE,WAAW;;;AAIrC,WAAW;EACT,eAAe,EAAE,IAAI;EACrB,KAAK,EA9CY,OAAkB;;AAgDrC,kBAAkB;EAChB,WAAW,EAAE,GAAG;EAChB,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,IAAI;EACV,YAAY,EAAE,GAAG;EAEjB,8EAAa;IACX,UAAU,EAAE,CAAC;EAEf,0NAAsC;IACpC,SAAS,EAAE,OAAO;IAClB,gSAAQ;MACN,WAAW,EAAE,MAAK;MAClB,KAAK,EAAE,KAAI;MACX,QAAQ,EAAE,QAAQ;MAClB,OAAO,EAAE,GAAG;;AAElB,EAAE;EACA,WAAW,EAAE,GAAG;EAChB,KAAK,EAtEQ,OAAe;;AAwE9B,EAAE;EACA,MAAM,EAAE,YAAuB;EAC/B,KAAK,EAzEM,OAAe;EA0E1B,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,GAAG;;AAElB,EAAE;EACA,MAAM,EAAE,aAAa;EACrB,SAAS,EAAE,IAAI;;AAEjB,EAAE;EACA,MAAM,EAAE,aAAa;EACrB,SAAS,EAAE,IAAI;;AAEjB,EAAE;EACA,MAAM,EAAE,aAAa;EACrB,WAAW,EAAE,GAAG;EAChB,SAAS,EAAE,OAAO;EAElB,OAAI;IACF,WAAW,EAAE,GAAG;;AAEpB,QAAQ;EACN,WAAW,EAAE,MAAM;EACnB,MAAM,EAAE,UAAU;;AAEpB,EAAE;EACA,UAAU,EAAE,IAAI;EAChB,aAAa,EAAE,GAAG;;AAEpB,CAAC;EACC,KAAK,EAtGM,OAAe;;AAwG5B,iBAAiB;EACf,MAAM,EAAE,MAAM;EACd,OAAO,EAAE,mBAAmB;EAC5B,aAAa,EArGM,GAAG;EAsGtB,KAAK,EAAE,IAAyB;EAChC,UAAU,EAAE,sBAAuB;EACnC,MAAM,EAAE,iBAA2B;EAEnC,2BAAI;IACF,UAAU,EAAE,kBAAkB;EAEhC,qBAAC;IACC,aAAa,EAAE,GAAG;EAEpB,2CAAY;IACV,aAAa,EAAE,CAAC;;AAEpB,mBAAmB;EACjB,OAAO,EAAE,OAAO;EAChB,UAAU,EAAE,mBAAmB;EAC/B,WAAW,EAAE,MAAM;;AAErB,IAAI;EACF,WAAW,EAAE,OAAO;;AAEtB,OAAO;EACL,UAAU,EAAE,MAAM;;;AAIpB,SAAS;EACP,WAAW,EAAE,GAAG;EAChB,UAAU,EAzIG,OAAe;EA0I5B,aAAa,EAAE,iBAA2B;EAK1C,YAAE;IGgMF,uBAAwC,EH9LrB,aAAa;IG8LhC,eAAwC,EH9LrB,aAAa;IAC9B,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,WAAW;IAEpB,oCAAiD;MAPnD,YAAE;QGgMF,sBAAwC,EHxLpB,MAAM;QGwL1B,cAAwC,EHxLpB,MAAM;QACtB,UAAU,EAAE,MAAM;EAEtB,YAAE;IGqLF,YAAwC,EHpLhC,QAAQ;IGoLhB,IAAwC,EHpLhC,QAAQ;EAEhB,WAAC;IACC,eAAe,EAAE,IAAI;IACrB,WAAW,EAAE,GAAG;IAChB,KAAK,EAAE,KAAK;IACZ,cAAc,EAAE,KAAI;EAGpB,mBAAC;IACC,WAAW,EAAE,GAAG;IAChB,cAAc,EAAE,KAAI;EAExB,wBAAc;IACZ,OAAO,EAAE,YAAY;IACrB,OAAO,EAAE,OAAO;IAChB,gBAAgB,EAAE,OAAyB;IAC3C,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;IACjB,KAAK,EAAE,KAAK;IACZ,aAAa,EAxKI,GAAG;IAyKpB,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,IAAI;IAET,gCAAO;MAEL,cAAc,EAAE,kBAAkB;;;AAMtC,eAAQ;EACN,OAAO,EAAE,cAAuB;EAChC,UAAU,EAzLG,OAAkB;EA0L/B,aAAa,EAAE,iBAA2B;AAE5C,kBAAW;EAET,UAAU,EAAE,MAAM;EAClB,MAAM,EAAE,KAAK;EACb,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,CAAC;EACV,IAAI,EAAE,IAAI;EACV,UAAU,EAAE,6CAA6C;EACzD,eAAe,EAAE,OAAO;AAE1B,SAAE;EACA,UAAU,EAAE,MAAM;EAClB,MAAM,EAAE,aAAa;EACrB,OAAO,EAAE,CAAC;EACV,IAAI,EAAE,CAAC;EACP,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,IAAI;EACjB,cAAc,EAAE,SAAS;AAE3B,kBAAW;EG4HX,mBAAwC,EHzHzB,MAAM;EGyHrB,WAAwC,EHzHzB,MAAM;EGyHrB,uBAAwC,EHxHrB,MAAM;EGwHzB,eAAwC,EHxHrB,MAAM;AAEzB,oBAAa;EACX,OAAO,EAAE,KAAK;EACd,MAAM,EAAE,QAAQ;EAChB,OAAO,EAAE,QAAQ;EACjB,aAAa,EAtNI,GAAG;EAuNpB,MAAM,EAAE,iBAAyB;EACjC,UAAU,EAAE,KAAK;EACjB,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,MAAM;AAEpB,oCAAiD;EAC/C,eAAQ;IACN,WAAW,EAAE,IAAI;IACjB,cAAc,EAAE,IAAI;EAEtB,SAAE;IACA,MAAM,EAAE,gBAAgB;IACxB,SAAS,EAAE,IAAI;EAEjB,kBAAW;IGmGb,sBAAwC,EHlGpB,MAAM;IGkG1B,cAAwC,EHlGpB,MAAM;;;AAK5B,MAAM;EACJ,OAAO,EAAE,MAAuB;EAChC,UAAU,EAAE,MAAM;EAClB,SAAS,EAAE,IAAI;EACf,KAAK,EArPM,OAAe;EAuP1B,oBAAa;IACX,UAAU,EAAE,CAAC;IACb,aAAa,EAAE,CAAC;IAChB,WAAW,EAAE,CAAC;IAEd,OAAO,EAAE,OAAO;IAChB,UAAU,EAAE,iBAAyB;EAEvC,WAAI;IACF,OAAO,EAAE,YAAY;IACrB,cAAc,EAAE,MAAM;EAGtB,iBAAC;IACC,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,MAAK;EAElB,oBAAa;IAEX,KAAK,EAAE,GAAG;IACV,QAAQ,EAAE,QAAQ;IAClB,IAAI,EAAE,MAAK;IAEX,yBAAI;MAEF,KAAK,EAAE,CAAC;IAGV,sBAAC;MACC,KAAK,EAAE,GAAG;MACV,OAAO,EAAE,MAAK;MACd,OAAO,EAAE,YAAY;;;AAI3B,aAAa;EI5RX,QAAQ,EAAE,MAAM;ECiBd,KAAK,EAAE,CAAC;EL8QV,UAAU,EAAE,IAAI;EAChB,aAAa,EAAE,IAAI;;AAErB,QAAQ;EACN,KAAK,EAvSS,KAAK;EAwSnB,UAAU,EAAE,GAAG;EACf,KAAK,EAAE,IAAI;EAIX,WAAE;IACA,SAAS,EAAE,IAAI;IACf,gBAAgB,EAAE,KAAK;IACvB,OAAO,EAAE,CAAC;IACV,KAAK,EAjTO,KAAK;IAkTjB,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,GAAG;EAElB,iBAAQ;IACN,KAAK,EAtTO,KAAK;IAuTjB,UAAU,EAAE,IAAI;EAElB,gCAAuB;IACrB,KAAK,EAAE,KAAK;IACZ,aAAa,EAAE,IAAI;IACnB,OAAO,EAAE,IAAI;IACb,cAAc,EAAE,GAAG;IAEnB,sCAAK;MACH,OAAO,EAAE,IAAI;MACb,YAAY,EAAE,KAAI;IAEpB,gDAAe;MACb,cAAc,EAAE,GAAG;MACnB,SAAS,EAAE,CAAC;EAIhB,oCAAwE;IAnC1E,QAAQ;MA0CJ,KAAK,EAAE,IAAI;MACX,KAAK,EAAE,IAAI;MANX,4CAAmC;QACjC,OAAO,EAAE,IAAI;MAMf,YAAG;QACD,aAAa,EAAE,CAAC;MAIlB,gCAAuB;QACrB,KAAK,EAAE,IAAI;QACX,sCAAK;UACH,OAAO,EAAE,MAAM;;AAMvB,oCAAwE;EACtE,mBAAmB;IACjB,WAAW,EAAE,KAAqB;IAClC,YAAY,EAAE,mBAA0D;AAE5E,oCAAuE;EACrE,mBAAmB;IACjB,YAAY,EAAE,IAAI;;AAItB,iBAAiB;EACf,aAAa,EAAE,IAAI;EACnB,SAAS,EAAE,IAAI;EAEf,oBAAE;IACA,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,CAAC;IAEV,0BAAK;MACH,OAAO,EAAE,UAAU;EAEvB,mBAAC;IACC,eAAe,EAAE,IAAI;IACrB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,KAAK;IAEd,yBAAO;MACL,KAAK,EAvXE,OAAe;;AAyX5B,2BAA2B;EACzB,OAAO,EAAE,SAAS;;;AAKpB,aAAa;EACX,aAAa,EA1XM,GAAG;EA2XtB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,SAAS;EAClB,UAAU,EAAE,OAAO;EACnB,MAAM,EAAE,iBAAiB;EACzB,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,IAAI;EACjB,MAAM,EAAE,KAAK;EACb,WAAW,EAAE,gBAAgB;;;AAK7B,oCAAM;EACJ,OAAO,EAAE,MAAM;EACf,WAAW,EAAE,CAAC;AAEhB,wBAAS;EACP,OAAO,EAAE,KAAK;EACd,OAAO,EAAE,GAAG;EACZ,MAAM,EAAE,KAAI;AAEd,yBAAU;EACR,OAAO,EAAE,GAAO;EAChB,SAAS,EAAE,MAAM;EACjB,YAAY,EAAE,GAAG;EACjB,QAAQ,EAAE,QAAQ;EAClB,WAAW,EAAE,OAAM;EACnB,WAAW,EAAE,KAAK;;;AAMtB,gBAAgB;EACd,UAAU,EA5ZI,GAAG;;AA8ZnB,6BAA6B;EAC3B,UAAU,EAAE,GAAG", "sources": ["highlight.scss","fontello.scss","all.sass","../../../../../../../usr/local/lib/ruby/gems/2.4.0/gems/compass-core-1.0.3/stylesheets/compass/typography/text/_replacement.scss","../../../../../../../usr/local/lib/ruby/gems/2.4.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_flexbox.scss","../../../../../../../usr/local/lib/ruby/gems/2.4.0/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../../../../usr/local/lib/ruby/gems/2.4.0/gems/compass-core-1.0.3/stylesheets/compass/utilities/general/_clearfix.scss","../../../../../../../usr/local/lib/ruby/gems/2.4.0/gems/compass-core-1.0.3/stylesheets/compass/utilities/general/_hacks.scss"], "names": [], "file": "all.css" diff --git a/stylesheets/all.sass b/stylesheets/all.sass index 54a46a2f5..aa3b62642 100644 --- a/stylesheets/all.sass +++ b/stylesheets/all.sass @@ -19,6 +19,7 @@ $color-masthead: rgb(235, 235, 235) $fonts-body: "Helvetica Neue", "Helvetica", Arial, "Open Sans", sans-serif $border-radius-main: 4px +$h2-margin-top: 2em /** Mixins */ @@ -83,7 +84,7 @@ h1 color: $color-accent h2 - margin: 50px 0 15px 0 + margin: $h2-margin-top 0 15px 0 color: $color-main font-size: 22px line-height: 1.3 @@ -115,14 +116,23 @@ th a color: $color-main -blockquote +blockquote, .note margin: 20px 0 - padding: 10px 15px 0 15px + padding: 10px 15px 10px 15px border-radius: $border-radius-main color: lighten($color-main, 15%) background: rgba($color-main, 0.04) border: 1px solid $color-light-rule + code + background: inherit !important + + p + margin-bottom: 6px + + p:last-child + margin-bottom: 0 + p > code, li > code padding: 1px 4px background: rgba(0, 0, 0, 0.06) @@ -131,6 +141,9 @@ p > code, li > code code font-weight: inherit +address + font-style: normal + /** Navigation */ .site-nav @@ -190,7 +203,7 @@ header background: $color-masthead border-bottom: 1px solid $color-light-rule - h1 + h1#json-api @extend %hide-text text-align: center height: 130px @@ -392,3 +405,33 @@ pre.highlight line-height: 16px margin: 2em 0 font-family: Menlo, monospace + + +/** Extensions page */ +.profiles-list + dt, dd + display: inline + margin-left: 0 + + dd::after + display: block + content: " " + height: .8em + + dt::before + content: "\2022" + font-size: 1.56em + margin-right: 1em + position: absolute + margin-left: -.66em + line-height: 1.1em + +/** Individual profile page */ +// Our profile pages have more sophisticated markup than our +// main format pages, necessitating slightly different CSS. +// This is a bit of a mess.. but so is this whole file. +.profile-page h2 + margin-top: $h2-margin-top + +.profile-page h1 + section h2 + margin-top: 1em From e4aff910bcea3336a72b5a84781604b18cef538d Mon Sep 17 00:00:00 2001 From: Ethan Resnick Date: Fri, 30 Nov 2018 15:03:40 -0500 Subject: [PATCH 4/8] docs: mark extensions page as provisional until 1.1 is finalized --- extensions/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/index.md b/extensions/index.md index 4ea22502d..0f5d289d7 100644 --- a/extensions/index.md +++ b/extensions/index.md @@ -5,6 +5,8 @@ show_sidebar: true redirect_from: /profiles --- +> Note: This page describes features from [version 1.1](/format/1.1/) of the JSON:API spec, and links to profiles that use those new features. Version 1.1 is in its release candidate stage, so there is a (very small) probability that the spec and/or these profiles could change before v1.1 is released on January 31, 2019 (provided there are two compliant implementations by that date; if not the release will wait until such implementations exist to prove its viability). + JSON:API can be extended with profiles. These profiles enable an API to provide clients with information or functionality beyond that described in the base JSON:API specification. From b5dc873ea108699f9795030d8234c0c42b738afb Mon Sep 17 00:00:00 2001 From: Ethan Resnick Date: Fri, 30 Nov 2018 15:18:29 -0500 Subject: [PATCH 5/8] feat: better status messages for the upcoming version pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Show the release date, when there is one, and add the concept of a “release candidate” stage (where the spec is subject to small changes based on implementor experience) vs a “working draft” stage (where we make no guarantees about what might still change, aside from our existing backwards compatibility promises). --- _format/upcoming/index.md | 2 ++ _includes/status.md | 27 +++++++++++++++++++-------- _layouts/page.html | 2 +- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/_format/upcoming/index.md b/_format/upcoming/index.md index 19273b6d0..57ae8da10 100644 --- a/_format/upcoming/index.md +++ b/_format/upcoming/index.md @@ -1,5 +1,7 @@ --- is_upcoming_version: true +status: rc +release_date: 2019-01-31 --- {% for spec_draft in site.format %} {% if spec_draft.version > site.latest_version and spec_draft.path contains 'index' %} diff --git a/_includes/status.md b/_includes/status.md index 8eea84fd2..496ecc15a 100644 --- a/_includes/status.md +++ b/_includes/status.md @@ -6,32 +6,43 @@ {% assign version = include.version %} {% assign is_latest_version_page = include.is_latest_version %} {% assign is_upcoming_version_page = include.is_upcoming_version %} +{% assign status = include.status %} ## Status {% comment %} - The first paragraph in each case, below, aims to explain what content - the page holds and how that may (or may not) change over time. + The first paragraph in each case below aims to explain what content + the page holds and whether that content is finalized. Note: all the text below must be outdented and markdownified where it's included for it to be rendered correctly as markdown. {% endcomment %} {% if is_latest_version_page %} - This page represents the latest published version of JSON:API, which is + This page presents the latest published version of JSON:API, which is currently version {{ site.latest_version }}. New versions of JSON:API **will always be backwards compatible** using a _never remove, only add_ strategy. Additions can be proposed in our [discussion forum](http://discuss.jsonapi.org/). {% elsif is_upcoming_version_page %} - This page represents the **working draft** for the next version of JSON:API, - which is currently expected to be {{ site.latest_version|plus:0.1 }}. + This page presents the **{% if status == "rc" %}release candidate{% else %} + working draft{% endif %}** for the next version of JSON:API, which is + expected to be {{ site.latest_version|plus:0.1 }}. {% if status != "rc" %} + As a draft, the content on this page is subject to change.{% else %}As a + release candidate, the content on this page is unlikely to change. However, + some changes may still occur if implementation experience proves that they are + necessary before this version is finalized.{% endif %} + + {% if include.release_date %} + This version is expected to be finalized and released on + **{{ include.release_date | date: "%B %e, %Y" }}** (provided there are two compliant implementations by that date; if not the release will wait until such implementations exist to prove its viability). + {% endif %} + {% elsif version and version > site.latest_version %} This page will always present the most recent text for JSON:API - v{{ site.latest_version|plus:0.1 }}. Currently, version - {{ site.latest_version|plus:0.1 }} is **still a draft**, so this text is - provisional. + v{{ site.latest_version|plus:0.1 }}. Version {{ site.latest_version|plus:0.1 }} + has not been finalized, so the text here may change. {% elsif version and version == site.latest_version %} This page presents an archived copy of JSON:API version {{ version }}. None diff --git a/_layouts/page.html b/_layouts/page.html index 780c3aa03..77adb7e9c 100644 --- a/_layouts/page.html +++ b/_layouts/page.html @@ -87,7 +87,7 @@

{% if page.is_spec_page %} {% capture status %} - {% include status.md version=page.version is_latest_version=page.is_latest_version is_upcoming_version=page.is_upcoming_version %} + {% include status.md release_date=page.release_date status=page.status version=page.version is_latest_version=page.is_latest_version is_upcoming_version=page.is_upcoming_version %} {% endcapture %} {{ status|strip|markdownify }} {% endif %} From 1e70d71602a1f10e9594825da9f22990bfadc3a6 Mon Sep 17 00:00:00 2001 From: Ethan Resnick Date: Sun, 2 Dec 2018 14:24:07 -0500 Subject: [PATCH 6/8] docs: add changelog entry for 1.1 changes --- index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/index.md b/index.md index 8443cd877..e60c40e31 100644 --- a/index.md +++ b/index.md @@ -125,6 +125,10 @@ You can [browse existing profiles](/extensions/#existing-profiles) or ## Update history +- 2018-12-01: 1.1 Release candidate announced. + - New features include: [profiles](https://jsonapi.org/format/1.1/#profiles), ["@-Members"](https://jsonapi.org/format/1.1/#document-member-names-at-members), and [error object `type` links](https://jsonapi.org/format/1.1/#error-objects). + - There are editorial clarifications around: [query parameters](https://jsonapi.org/format/1.1/#query-parameters) (their parsing/serialization, and reserved parameter names), the appropriate status code for [specific](https://github.com/json-api/json-api/pull/1036) [responses](https://github.com/json-api/json-api/pull/1029), and the [presence of the `included` key](https://github.com/json-api/json-api/pull/1236) even when its value is an empty array. + - JSON:API switched to [recommending camelCased names](https://jsonapi.org/recommendations/#naming). - 2015-05-29: 1.0 final released. - 2015-05-21: Release candidate 4 released. - 2015-03-16: Release candidate 3 released. From bba04ae0044a120fd57e4700ffa687a61b885b2e Mon Sep 17 00:00:00 2001 From: Ethan Resnick Date: Sun, 2 Dec 2018 15:51:32 -0500 Subject: [PATCH 7/8] docs: format page reform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `/format/upcoming/` url still exists (in case it’s ever necessary to reference “the next version, whatever that may be at the time the link is followed”). However, it now simply redirects to `/format/1.1/` rather than having its own content. It’s status content previously was a bit confusing, and there wasn’t much reason for it to be a dedicated page. Additionally, it was confusing to have two links to v1.1 in the version picker (the upcoming link and the 1.1 permalink). So, now, the version picker excludes a separate permalink entry for v1.1, and instead has the picker entry for the “Upcoming spec” simply go to the `/format/1.1/` page. --- _format/1.1/index.md | 2 ++ _format/upcoming/index.md | 21 ++++++--------------- _includes/status.md | 28 ++++++++++------------------ _includes/title_for_version.md | 4 ---- _layouts/page.html | 10 +++++----- 5 files changed, 23 insertions(+), 42 deletions(-) diff --git a/_format/1.1/index.md b/_format/1.1/index.md index 6273e65af..27dfec236 100644 --- a/_format/1.1/index.md +++ b/_format/1.1/index.md @@ -1,5 +1,7 @@ --- version: 1.1 +status: rc +release_date: 2019-01-31 --- ## Introduction diff --git a/_format/upcoming/index.md b/_format/upcoming/index.md index 57ae8da10..9712a092d 100644 --- a/_format/upcoming/index.md +++ b/_format/upcoming/index.md @@ -1,17 +1,8 @@ --- -is_upcoming_version: true -status: rc -release_date: 2019-01-31 +# Note: We have to do a `redirect_to` here rather than a redirect_from +# in the file for the latest spec version, as the latter causes jekyll +# generate a redirect to `/format/{version}/index.html`, which is an ugly +# and non-canonical url, and jekyll's url config settings aren't flexible +# enough to prevent this. +redirect_to: /format/1.1/ --- -{% for spec_draft in site.format %} - {% if spec_draft.version > site.latest_version and spec_draft.path contains 'index' %} - {% comment %} - The line below must be outdented (ugly as that is) or it will be parsed - differently, since indentation can be significant in markdown (e.g. to - indicate code blocks). - {% endcomment %} - -{{ spec_draft.content }} - - {% endif %} -{% endfor %} diff --git a/_includes/status.md b/_includes/status.md index 496ecc15a..3aa0ccd75 100644 --- a/_includes/status.md +++ b/_includes/status.md @@ -5,7 +5,6 @@ {% assign version = include.version %} {% assign is_latest_version_page = include.is_latest_version %} -{% assign is_upcoming_version_page = include.is_upcoming_version %} {% assign status = include.status %} ## Status @@ -24,26 +23,20 @@ always be backwards compatible** using a _never remove, only add_ strategy. Additions can be proposed in our [discussion forum](http://discuss.jsonapi.org/). -{% elsif is_upcoming_version_page %} - This page presents the **{% if status == "rc" %}release candidate{% else %} - working draft{% endif %}** for the next version of JSON:API, which is - expected to be {{ site.latest_version|plus:0.1 }}. {% if status != "rc" %} - As a draft, the content on this page is subject to change.{% else %}As a - release candidate, the content on this page is unlikely to change. However, - some changes may still occur if implementation experience proves that they are - necessary before this version is finalized.{% endif %} +{% elsif version and version > site.latest_version %} + This page will always present the most recent text for JSON:API v{{ site.latest_version|plus:0.1 }}. + Version {{ site.latest_version|plus:0.1 }} is a **{% if status == "rc" %}release + candidate{% else %}working draft{% endif %}**. As such, the content on this + page {% if status != "rc" %}is subject to change.{% else %}is unlikely to + change. However, some changes may still occur if implementation experience + proves that they are necessary before this version is finalized.{% endif %} {% if include.release_date %} - This version is expected to be finalized and released on - **{{ include.release_date | date: "%B %e, %Y" }}** (provided there are two compliant implementations by that date; if not the release will wait until such implementations exist to prove its viability). + This version is expected to be finalized and released on **{{ include.release_date | date: "%B %e, %Y" }}** + (provided there are two compliant implementations by that date; if not the + release will wait until such implementations exist to prove its viability). {% endif %} - -{% elsif version and version > site.latest_version %} - This page will always present the most recent text for JSON:API - v{{ site.latest_version|plus:0.1 }}. Version {{ site.latest_version|plus:0.1 }} - has not been finalized, so the text here may change. - {% elsif version and version == site.latest_version %} This page presents an archived copy of JSON:API version {{ version }}. None of the normative text on this page will change. **Subsequent versions of @@ -55,7 +48,6 @@ of the normative text on this page will change. While {{ version }} is no longer the [latest version](/format/) of JSON:API, **new versions will remain compatible with this one**, as JSON:API uses a _never remove, only add_ strategy. - {% endif %} {% comment %} diff --git a/_includes/title_for_version.md b/_includes/title_for_version.md index 1a5ccfba4..e05658712 100644 --- a/_includes/title_for_version.md +++ b/_includes/title_for_version.md @@ -13,14 +13,10 @@ {% endcomment %} {% assign version = include.version %} {% assign is_latest_version_page = include.is_latest_version %} -{% assign is_upcoming_version_page = include.is_upcoming_version %} {% if is_latest_version_page %} Latest Specification (v{{ site.latest_version }}) -{% elsif is_upcoming_version_page %} - Draft for Next Specification Release - {% elsif version and version > site.latest_version %} Specification v{{site.latest_version|plus:0.1}} (Still in Development) diff --git a/_layouts/page.html b/_layouts/page.html index 77adb7e9c..12be4b8a5 100644 --- a/_layouts/page.html +++ b/_layouts/page.html @@ -13,7 +13,7 @@ {% if page.is_spec_page %} {% capture page_title %} - {% include title_for_version.md is_latest_version=page.is_latest_version is_upcoming_version=page.is_upcoming_version version=page.version %} + {% include title_for_version.md is_latest_version=page.is_latest_version version=page.version %} {% endcapture %} {% else %} {% assign page_title = page.title %} @@ -53,15 +53,15 @@

A specification for building APIs in JSON

Latest Version (v{{ site.latest_version }}) {% assign sorted_formats = site.format|sort:'version' %} {% for spec_draft in sorted_formats %} - {% if spec_draft.version and spec_draft.path contains 'index' %} + {% if spec_draft.version <= site.latest_version and spec_draft.path contains 'index' %}

{% endif %} diff --git a/stylesheets/all.css b/stylesheets/all.css index fab5a3766..bb6910285 100644 --- a/stylesheets/all.css +++ b/stylesheets/all.css @@ -232,7 +232,7 @@ address { /** Header */ header .content { - padding: 29px 20px 41px; + padding: 32px 20px 41px; background: #ebebeb; border-bottom: 1px solid #cccccc; } header h1#json-api { @@ -245,7 +245,7 @@ header h1#json-api { background-size: contain; } header h2 { text-align: center; - margin: 15px 0 40px 0; + margin: 17px 0 37px 0; padding: 0; left: 0; font-size: 124%; @@ -265,6 +265,16 @@ header .quicklinks a { background: white; text-decoration: none; text-align: center; } +header .announcement { + margin: 22px auto 0; + max-width: 38em; + text-align: center; + position: relative; + top: 15px; + color: #5a5a5a; } + header .announcement * { + color: inherit; + margin: 0; } @media screen and (max-width: 800px) { header .content { padding-top: 20px; diff --git a/stylesheets/all.css.map b/stylesheets/all.css.map index b414463a8..d7e0d24e7 100644 --- a/stylesheets/all.css.map +++ b/stylesheets/all.css.map @@ -1,6 +1,6 @@ { "version": 3, -"mappings": "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", +"mappings": "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", "sources": ["highlight.scss","fontello.scss","all.sass","../../../../../../../usr/local/lib/ruby/gems/2.4.0/gems/compass-core-1.0.3/stylesheets/compass/typography/text/_replacement.scss","../../../../../../../usr/local/lib/ruby/gems/2.4.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_flexbox.scss","../../../../../../../usr/local/lib/ruby/gems/2.4.0/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../../../../usr/local/lib/ruby/gems/2.4.0/gems/compass-core-1.0.3/stylesheets/compass/utilities/general/_clearfix.scss","../../../../../../../usr/local/lib/ruby/gems/2.4.0/gems/compass-core-1.0.3/stylesheets/compass/utilities/general/_hacks.scss"], "names": [], "file": "all.css" diff --git a/stylesheets/all.sass b/stylesheets/all.sass index aa3b62642..e142db93b 100644 --- a/stylesheets/all.sass +++ b/stylesheets/all.sass @@ -199,7 +199,7 @@ address header .content - padding: 29px $page-padding 41px + padding: 32px $page-padding 41px background: $color-masthead border-bottom: 1px solid $color-light-rule @@ -215,7 +215,7 @@ header h2 text-align: center - margin: 15px 0 40px 0 + margin: 17px 0 37px 0 padding: 0 left: 0 font-size: 124% @@ -238,6 +238,18 @@ header text-decoration: none text-align: center + .announcement + margin: 22px auto 0 + max-width: 38em + text-align: center + position: relative + top: 15px // intentionally eat into parent's padding-bottom + color: $color-main + + * + color: inherit + margin: 0 + @media screen and (max-width: $mobile-breakpoint) .content padding-top: 20px pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy