diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..2e3b749a --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,31 @@ +name: gh-pages + +on: + push: + branches: + - master + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Build with Node.js + uses: actions/setup-node@v1 + with: + node-version: '12.x' + - run: npm install + - run: npm run build + + - name: GitHub Pages action + uses: peaceiris/actions-gh-pages@v2.5.1 + env: + ACTIONS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }} + PUBLISH_BRANCH: gh-pages + PUBLISH_DIR: ./html/.vuepress/dist/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..19df328c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +html/ diff --git a/.vuepress/README.md b/.vuepress/README.md new file mode 100644 index 00000000..7c43bff1 --- /dev/null +++ b/.vuepress/README.md @@ -0,0 +1,11 @@ +--- +editLink: false +--- + +# IPLD Specifications + +Specifications for the Inter-planetary Linked Data (IPLD) project: + +* **[IPLD Schemas](./schemas/)** + +See more or contribute on [GitHub](https://github.com/ipld/specs/). \ No newline at end of file diff --git a/.vuepress/config.js b/.vuepress/config.js new file mode 100644 index 00000000..2239b669 --- /dev/null +++ b/.vuepress/config.js @@ -0,0 +1,55 @@ +require('./highlight') + +function linkfix (md) { + const defaultRender = md.renderer.rules.link_open + + md.renderer.rules.link_open = function (tokens, idx, options, env, self) { + const hrefIndex = tokens[idx].attrIndex('href'); + if (hrefIndex > -1) { + const href = tokens[idx].attrs[hrefIndex][1] + if (/\.(ipldsch|json)$/.test(href)) { + tokens[idx].attrs[hrefIndex][1] = `${href}.md` + } + } + + return defaultRender(tokens, idx, options, env, self) + } +} + +module.exports = { + title: 'IPLD Specifications', + description: 'Specifications for the Inter-planetary Linked Data project', + base: '/', + themeConfig: { + repo: 'ipld/specs', + editLinks: true, + editLinkText: 'Edit this page on GitHub', + lastUpdated: 'Last Updated', + smoothScroll: true, + nav: [ + { text: 'Home', link: '/' }, + { text: 'IPLD Schemas', link: '/schemas/' } + ], + sidebar: { + '/schemas/': [{ + title: 'IPLD Schemas', + collapsable: false, + sidebarDepth: 2, + children: [ + ['goals', 'Goals'], + ['feature-summary', 'Feature Summary'], + ['introduction', 'Introduction'], + ['authoring-guide', 'Authoring Guide'], + 'links', + 'schema-kinds', + ['representations', 'Representations'], + ['advanced-layouts', 'Advanced Layouts'] + ] + }] + } + }, + extendMarkdown: md => { + // use more markdown-it plugins! + md.use(linkfix) + } +} diff --git a/.vuepress/highlight.js b/.vuepress/highlight.js new file mode 100644 index 00000000..75b762d9 --- /dev/null +++ b/.vuepress/highlight.js @@ -0,0 +1,36 @@ +// this require is awkward but technically the proper way to find the 'prismjs' +// that's used by vuepress -> @vuepress/markdown -> prismjs +const prism = require( + require.resolve('prismjs', + require.resolve('@vuepress/markdown', + require.resolve('vuepress')))) + +prism.languages.ipldsch = { + typedef: { + pattern: /^[ \t]*(?:type|advanced)[ \t][A-Z](_?[A-Za-z0-9])*\b/m, + inside: { + keyword: /^[ \t]*(type|advanced)/m, + 'class-name': /[\w]+$/ + } + }, + keyword: /\b(?:bool|int|float|string|bytes|null|nullable|optional)\b/, + builtin: /\b(struct|union|enum)(?=[ \t]*\{)\b/, + representation: { + pattern: /^}[ \t]representation\b/m, + inside: { + builtin: /representation/ + } + }, + operator: /=/, + number: /\b-?\d+\.?\d*(?:e[+-]?\d+)?\b/i, + punctuation: /[(){}:[\]\|&]/, + string: { + pattern: /(")(?:\\[\s\S]|(?!\1)[^\\])*\1/, + greedy: true + }, + comment: { + pattern: /(^|[^"])#.*/, + lookbehind: true, + greedy: true + } +} diff --git a/.vuepress/styles/index.styl b/.vuepress/styles/index.styl new file mode 100644 index 00000000..e2224669 --- /dev/null +++ b/.vuepress/styles/index.styl @@ -0,0 +1,3 @@ +div[class~="language-ipldsch"]::before { + content: "ipld schema"; +} diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..901248c1 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +specs.ipld.io diff --git a/package.json b/package.json new file mode 100644 index 00000000..f325750b --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "scripts": { + "prepare:base": "rm -rf html && mkdir html && cp -a .vuepress/ html/.vuepress/ && mv html/.vuepress/README.md html/", + "prepare:content": "cp -a schemas/ html/schemas/", + "prepare:ipldsch": "cd html && find . -name \\*.ipldsch -exec sh -c \"echo '---\\neditLink: false\\n---\\n\\n\\`\\`\\`ipldsch' > {}.md && cat {} >> {}.md && echo '\\`\\`\\`' >> {}.md\" \\;", + "prepare:json": "find html/ -name \\*.json -exec sh -c \"echo '---\\neditLink: false\\n---\\n\\n\\`\\`\\`json' > {}.md && cat {} >> {}.md && echo '\\`\\`\\`' >> {}.md\" \\;", + "build:vue": "vuepress build html --no-cache", + "build": "set -e; for t in prepare:base prepare:content prepare:ipldsch prepare:json build:vue; do npm run $t; done", + "serve": "echo '\n\n\u001b[1mView IPLD Specs @ http://localhost:1337/\u001b[22m\n\n'; npx st --dir html/.vuepress/dist --no-cache --index index.html" + }, + "dependencies": { + "vuepress": "^1.2.0" + } +} diff --git a/schemas/authoring-guide.md b/schemas/authoring-guide.md index 0f36debc..b3bcbc16 100644 --- a/schemas/authoring-guide.md +++ b/schemas/authoring-guide.md @@ -142,7 +142,7 @@ Links in IPLD Schemas are a special-case. The Data Model kind "Link" is expresse Links can be typedef'd, `type Foo &Bar` or can appear inline: `type Baz {String:&Bang}`. -Further, the type name is not a strict assertion that can be directly tested against underlying data, it is simply a hint regarding what should be found when following the link identified by the [CID](../block-layer/CID.md) at the position indicated by the Schema link. Strict assertions of this expected type may be applied at layers above the Schema validation layer when the link is resolved and the node decoded. +Further, the type name is not a strict assertion that can be directly tested against underlying data, it is simply a hint regarding what should be found when following the link identified by the [CID](https://github.com/ipld/specs/blob/master/block-layer/CID.md) at the position indicated by the Schema link. Strict assertions of this expected type may be applied at layers above the Schema validation layer when the link is resolved and the node decoded. For more information about Links in Schemas, see [Links and IPLD Schemas](./links.md). @@ -819,7 +819,7 @@ IPLD Schemas are intended to serve a documentation role as well as a programmati When embedding IPLD Schema declarations in Markdown, use code blocks with the language marker `ipldsch`, i.e.: -
+

 ```ipldsch
 type Foo struct {
   a   Int
@@ -829,7 +829,7 @@ type Foo struct {
 
 type Message string
 ```
-
+
Any such block found in a Markdown document will be extracted and stitched together to form a single Schema document. diff --git a/schemas/goals.md b/schemas/goals.md index dfd58fd8..d0cf78b2 100644 --- a/schemas/goals.md +++ b/schemas/goals.md @@ -1,7 +1,7 @@ # IPLD Schemas Goals 1. Provide a reasonable, easy to use, general type system for declaring useful properties about data. -2. Compose nicely over the [IPLD Data Model](../data-model-layer/data-model.md): Schemas should be usable with any data format you can build an [IPLD Codec](../block-layer/codecs/README.md) for. +2. Compose nicely over the [IPLD Data Model](https://github.com/ipld/specs/blob/master/data-model-layer/data-model.md): Schemas should be usable with any data format you can build an [IPLD Codec](https://github.com/ipld/specs/tree/master/block-layer/codecs) for. 3. Be efficient to verify: predictable; roughly linear in the size of the data and Schema; and absolutely not turing complete. 4. Be language-agnostic: many compatible implementations of the Schema tooling should exist, as well as bindings for many languages. 5. Assist rather than obstruct migration: we expect to be working with _existing_ data; we need to work well on this case. diff --git a/schemas/introduction.md b/schemas/introduction.md index 476096ef..8e83c331 100644 --- a/schemas/introduction.md +++ b/schemas/introduction.md @@ -4,7 +4,7 @@ IPLD concerns itself with the data layer of the distributed web. Its scope begins above the data storage and transmission layer, only interested in how data elements are encoded and decoded to a particular storage format and then presented in a consistent and usable form when above this encoding layer. -IPLD uses a [Data Model](../data-model-layer/data-model.md) to bound what form its standard data elements can take. The data model allows for standard scalar data types found across most programming languages and a large number of generic data encoding formats (JSON, CBOR, etc.), such as String and Int. It also includes two recursive types that are used to build more complex data structures upon the scalar types. These recursive types are List and Map and should be familiar to most programmers and are also common in many generic data encoding formats. The IPLD Data Model doesn’t include many of the types available in some encoding formats (such as the many Int sizing options available in CBOR). Similarly, it doesn’t support many of these same types available in some programming languages. Instead, it uses this bounded data presentation model as a way to build practical tools that can span many encoding formats and be practically usable in many programming languages. +IPLD uses a [Data Model](https://github.com/ipld/specs/blob/master/data-model-layer/data-model.md) to bound what form its standard data elements can take. The data model allows for standard scalar data types found across most programming languages and a large number of generic data encoding formats (JSON, CBOR, etc.), such as String and Int. It also includes two recursive types that are used to build more complex data structures upon the scalar types. These recursive types are List and Map and should be familiar to most programmers and are also common in many generic data encoding formats. The IPLD Data Model doesn’t include many of the types available in some encoding formats (such as the many Int sizing options available in CBOR). Similarly, it doesn’t support many of these same types available in some programming languages. Instead, it uses this bounded data presentation model as a way to build practical tools that can span many encoding formats and be practically usable in many programming languages. IPLD’s Data Model is useful for building an abstraction at the data layer. It pushes concerns about encoding and decoding to its own dedicated domain where such concerns only have to deal with a limited set of data types and how to convert to and from those data types. But it also makes room for the development of an ecosystem of libraries and tools that are able to build on top of this model and can therefore operate according to shared assumptions about how data is presented. Such an ecosystem should empower significantly more sharing of algorithms, tools, techniques and code in the distributed web community, rather than siloing these assets in codebases that are concerned entirely use-case-specific stacks. diff --git a/schemas/links.md b/schemas/links.md index 42d35332..d0310ed0 100644 --- a/schemas/links.md +++ b/schemas/links.md @@ -83,6 +83,6 @@ type Element union { # ... further definitions for `Bucket` ``` -In this example, from the [HashMap](../data-structures/hashmap.md) spec, we describe a `map`, named `HashMapNode` that contains a `data` property which is a list of `Element`s. These `Element`s may be one of three things: a `map` that contains another `HashMapNode` (an inlined child for a tree data structure), a `link` which is assumed to lead to a `HashMapNode` (a linked child) or a `Bucket` (not described here) which comprises a `list`. +In this example, from the [HashMap](https://github.com/ipld/specs/blob/master/data-structures/hashmap.md) specification, we describe a `map`, named `HashMapNode` that contains a `data` property which is a list of `Element`s. These `Element`s may be one of three things: a `map` that contains another `HashMapNode` (an inlined child for a tree data structure), a `link` which is assumed to lead to a `HashMapNode` (a linked child) or a `Bucket` (not described here) which comprises a `list`. Our validator can scan the `data` list and check that each element is one of: `map`, `link` and `list`. We make no strong assertions that the `link` actually yields a `HashMapNode` but such assertions may be built into code generated from this schema _when_ the link is loaded and validated. diff --git a/schemas/schema-kinds.md b/schemas/schema-kinds.md index 316a21c3..7750f2d3 100644 --- a/schemas/schema-kinds.md +++ b/schemas/schema-kinds.md @@ -233,11 +233,15 @@ expose and correctly preserve the value's presense or absence. -
+
+
+```ipldsch
 type Foo struct {
 	bar Bool
 }
-
+``` + + {"bar": true}
{"bar": false}
@@ -247,11 +251,15 @@ type Foo struct { -
+
+
+```ipldsch
 type Foo struct {
 	bar nullable Bool
 }
-
+``` + + {"bar": true}
{"bar": false}
@@ -262,11 +270,15 @@ type Foo struct { -
+
+
+```ipldsch
 type Foo struct {
 	bar optional Bool
 }
-
+``` + + {"bar": true}
{"bar": false}
@@ -277,11 +289,15 @@ type Foo struct { -
+
+
+```ipldsch
 type Foo struct {
 	bar optional nullable Bool
 }
-
+``` + + {"bar": true}
{"bar": false}
@@ -293,13 +309,17 @@ type Foo struct { -
+
+
+```ipldsch
 type Foo struct {
 	bar Bool
 } representation map {
 	field bar default "false"
 }
-
+``` + + {"bar": true}
{}