├── .all-contributorsrc ├── .ci ├── azure-pipelines.yml ├── prepare-release.sh └── publish-docs.sh ├── .dockerignore ├── .editorconfig ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── examples ├── article.ts ├── article │ ├── complex.article.yaml │ └── simple.article.yaml ├── brand │ └── simple.brand.yaml ├── collection.invalid.yaml ├── collection.ts ├── collection.yaml ├── contactPoint │ └── simple.ContactPoint.yaml ├── datatable.ts ├── datatables │ └── simple.datatable.yaml ├── emphasis │ ├── invalid.emphasis.yaml │ └── simple.emphasis.yaml ├── heading │ ├── invalid.heading.yaml │ └── simple.heading.yaml ├── imageObjects │ ├── invalid.imageObject.yaml │ └── simple.imageObject.yaml ├── invalid │ ├── invalid.brand.yaml │ ├── invalid.contactPoint.yaml │ └── invalid.organization.yaml ├── link │ ├── simple.link.yaml │ └── withRelationship.link.yaml ├── list │ ├── nested.list.yaml │ └── simple.list.yaml ├── listItem │ ├── nested.listItem.yaml │ └── simple.listItem.yaml ├── mediaObject.yaml ├── organization │ └── simple.organization.yaml ├── paragraph │ ├── invalid.paragraph.yaml │ ├── nested.paragraph.yaml │ └── simple.paragraph.yaml ├── product │ └── simple.product.yaml ├── quote │ ├── attributed.quote.yaml │ └── simple.quote.yaml ├── quoteBlock │ ├── attributed.quoteBlock.yaml │ └── simple.quoteBlock.yaml ├── software │ ├── invalid.softwareApplication.yaml │ ├── invalid.softwareSession.yaml │ ├── invalid.softwareSourceCode.yaml │ ├── simple.softwareApplication.yaml │ ├── simple.softwareSession.yaml │ └── simple.softwareSourceCode.yaml ├── strong │ ├── nested.strong.yaml │ └── simple.strong.yaml ├── table │ ├── header.table.yaml │ ├── irregularHeader.table.yaml │ └── simple.table.yaml ├── tableCell │ ├── allProperties.tableCell.yaml │ ├── inlineContent.tableCell.yaml │ └── simple.tableCell.yaml ├── tableRow │ ├── multipleRows.tableRow.yaml │ └── simple.tableRow.yaml └── thematicBreak │ └── simple.thematicBreak.yaml ├── netlify.toml ├── package-lock.json ├── package.json ├── python ├── .gitignore ├── .mypy.ini ├── .pylintrc ├── MANIFEST.in ├── Makefile ├── README.md ├── requirements-dev.txt ├── setup.py ├── stencila │ └── schema │ │ ├── __init__.py │ │ ├── json.py │ │ ├── types.py │ │ └── util.py ├── tests │ ├── test_article.py │ ├── test_json.py │ └── test_util.py └── tox.ini ├── r ├── .Rbuildignore ├── .covrignore ├── .gitignore ├── .lintr ├── DESCRIPTION ├── Makefile ├── NAMESPACE ├── R │ ├── types.R │ └── typing.R ├── README.md ├── _pkgdown.yml ├── inst │ └── WORDLIST ├── r.Rproj └── tests │ ├── testthat.R │ └── testthat │ ├── helpers.R │ ├── test-types.R │ └── test-typing.R ├── rust ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Makefile ├── README.md ├── src │ ├── lib.rs │ ├── prelude.rs │ ├── schemas.rs │ └── types.rs └── tests │ ├── sizes.rs │ └── test.rs ├── schema ├── Array.schema.yaml ├── ArrayValidator.schema.yaml ├── Article.schema.yaml ├── AudioObject.schema.yaml ├── BlockContent.schema.yaml ├── Boolean.schema.yaml ├── BooleanValidator.schema.yaml ├── Brand.schema.yaml ├── CitationIntentEnumeration.schema.yaml ├── Cite.schema.yaml ├── CiteGroup.schema.yaml ├── Claim.schema.yaml ├── Code.schema.yaml ├── CodeBlock.schema.yaml ├── CodeChunk.schema.yaml ├── CodeError.schema.yaml ├── CodeExecutable.schema.yaml ├── CodeExpression.schema.yaml ├── CodeFragment.schema.yaml ├── Collection.schema.yaml ├── Comment.schema.yaml ├── ConstantValidator.schema.yaml ├── ContactPoint.schema.yaml ├── CreativeWork.schema.yaml ├── Datatable.schema.yaml ├── DatatableColumn.schema.yaml ├── Date.schema.yaml ├── DefinedTerm.schema.yaml ├── Delete.schema.yaml ├── Emphasis.schema.yaml ├── Entity.schema.yaml ├── EnumValidator.schema.yaml ├── Enumeration.schema.yaml ├── Figure.schema.yaml ├── Function.schema.yaml ├── Grant.schema.yaml ├── Heading.schema.yaml ├── ImageObject.schema.yaml ├── Include.schema.yaml ├── InlineContent.schema.yaml ├── Integer.schema.yaml ├── IntegerValidator.schema.yaml ├── Link.schema.yaml ├── List.schema.yaml ├── ListItem.schema.yaml ├── Mark.schema.yaml ├── Math.schema.yaml ├── MathBlock.schema.yaml ├── MathFragment.schema.yaml ├── MediaObject.schema.yaml ├── MonetaryGrant.schema.yaml ├── Node.schema.yaml ├── NontextualAnnotation.schema.yaml ├── Note.schema.yaml ├── Null.schema.yaml ├── Number.schema.yaml ├── NumberValidator.schema.yaml ├── Object.schema.yaml ├── Organization.schema.yaml ├── Paragraph.schema.yaml ├── Parameter.md ├── Parameter.schema.yaml ├── Periodical.schema.yaml ├── Person.md ├── Person.schema.yaml ├── PostalAddress.schema.yaml ├── Product.schema.yaml ├── PropertyValue.schema.yaml ├── PublicationIssue.schema.yaml ├── PublicationVolume.schema.yaml ├── Quote.md ├── Quote.schema.yaml ├── QuoteBlock.md ├── QuoteBlock.schema.yaml ├── Review.schema.yaml ├── SoftwareApplication.schema.yaml ├── SoftwareEnvironment.schema.yaml ├── SoftwareSession.schema.yaml ├── SoftwareSourceCode.schema.yaml ├── String.schema.yaml ├── StringValidator.schema.yaml ├── Strong.md ├── Strong.schema.yaml ├── Subscript.md ├── Subscript.schema.yaml ├── Superscript.schema.yaml ├── Table.md ├── Table.schema.yaml ├── TableCell.md ├── TableCell.schema.yaml ├── TableRow.md ├── TableRow.schema.yaml ├── ThematicBreak.schema.yaml ├── Thing.schema.yaml ├── TupleValidator.schema.yaml ├── Validator.schema.yaml ├── Variable.schema.yaml ├── VideoObject.schema.yaml └── VolumeMount.schema.yaml ├── ts ├── .gitignore ├── JsonSchema.ts ├── README.md ├── __fixtures__ │ ├── invalid.Cite.json │ └── valid.Cite.json ├── __tests__ │ ├── __snapshots__ │ │ └── validation.test.ts.snap │ ├── helpers.ts │ ├── matchers.ts │ ├── setup.ts │ └── validation.test.ts ├── bindings │ ├── __file_snapshots__ │ │ ├── BlockContent.R │ │ ├── BlockContent.py │ │ ├── Person.R │ │ └── Person.py │ ├── jsonld.ts │ ├── python.test.ts │ ├── python.ts │ ├── r.test.ts │ ├── r.ts │ ├── rust.ts │ ├── typescript.test.ts │ ├── typescript.ts │ └── vscode.ts ├── docs.ts ├── imports │ └── cito.ts ├── index.browser.ts ├── index.ts ├── schema.test.ts ├── schema.ts ├── types.test.ts ├── types.ts └── util │ ├── guards.test.ts │ ├── guards.ts │ ├── helpers.ts │ ├── index.browser.ts │ ├── index.ts │ ├── jsonSchemas.test.ts │ ├── jsonSchemas.ts │ ├── jsonld.test.ts │ ├── jsonld.ts │ ├── microdata.test.ts │ ├── microdata.ts │ ├── nodeType.test.ts │ ├── nodeType.ts │ ├── version.test.ts │ └── version.ts ├── tsconfig.browser.json ├── tsconfig.docs.json ├── tsconfig.json └── tsconfig.lib.json /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "schema", 3 | "projectOwner": "stencila", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": [ 7 | "README.md" 8 | ], 9 | "imageSize": 100, 10 | "commit": false, 11 | "commitConvention": "angular", 12 | "contributors": [ 13 | { 14 | "login": "100ideas", 15 | "name": "Mac Cowell", 16 | "avatar_url": "https://avatars0.githubusercontent.com/u/57006?v=4", 17 | "profile": "http://has100ideas.com", 18 | "contributions": [ 19 | "code", 20 | "ideas" 21 | ] 22 | }, 23 | { 24 | "login": "jwijay", 25 | "name": "Jacqueline", 26 | "avatar_url": "https://avatars1.githubusercontent.com/u/10161095?v=4", 27 | "profile": "http://toki.io", 28 | "contributions": [ 29 | "code", 30 | "doc", 31 | "ideas" 32 | ] 33 | }, 34 | { 35 | "login": "beneboy", 36 | "name": "Ben Shaw", 37 | "avatar_url": "https://avatars1.githubusercontent.com/u/292725?v=4", 38 | "profile": "https://github.com/beneboy", 39 | "contributions": [ 40 | "code", 41 | "ideas", 42 | "infra", 43 | "doc" 44 | ] 45 | }, 46 | { 47 | "login": "alex-ketch", 48 | "name": "Alex Ketch", 49 | "avatar_url": "https://avatars2.githubusercontent.com/u/1646307?v=4", 50 | "profile": "http://ketch.me", 51 | "contributions": [ 52 | "code", 53 | "doc", 54 | "design" 55 | ] 56 | }, 57 | { 58 | "login": "nokome", 59 | "name": "Nokome Bentley", 60 | "avatar_url": "https://avatars0.githubusercontent.com/u/1152336?v=4", 61 | "profile": "https://github.com/nokome", 62 | "contributions": [ 63 | "code", 64 | "doc", 65 | "ideas" 66 | ] 67 | }, 68 | { 69 | "login": "asisiuc", 70 | "name": "asisiuc", 71 | "avatar_url": "https://avatars0.githubusercontent.com/u/17000527?v=4", 72 | "profile": "https://github.com/asisiuc", 73 | "contributions": [ 74 | "code", 75 | "ideas" 76 | ] 77 | }, 78 | { 79 | "login": "apawlik", 80 | "name": "Aleksandra Pawlik", 81 | "avatar_url": "https://avatars2.githubusercontent.com/u/2358535?v=4", 82 | "profile": "https://github.com/apawlik", 83 | "contributions": [ 84 | "code", 85 | "doc", 86 | "ideas" 87 | ] 88 | }, 89 | { 90 | "login": "vsoch", 91 | "name": "Vanessasaurus", 92 | "avatar_url": "https://avatars0.githubusercontent.com/u/814322?v=4", 93 | "profile": "https://vsoch.github.io", 94 | "contributions": [ 95 | "ideas", 96 | "code" 97 | ] 98 | }, 99 | { 100 | "login": "rgieseke", 101 | "name": "Robert Gieseke", 102 | "avatar_url": "https://avatars.githubusercontent.com/u/198537?v=4", 103 | "profile": "https://github.com/rgieseke", 104 | "contributions": [ 105 | "ideas", 106 | "code", 107 | "doc" 108 | ] 109 | } 110 | ], 111 | "contributorsPerLine": 7, 112 | "skipCi": true 113 | } 114 | -------------------------------------------------------------------------------- /.ci/prepare-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script to prepare a release by generating files before they are committed etc 4 | # Used by @semantic-release/exec 5 | 6 | VERSION=$1 7 | echo "Preparing release $VERSION" 8 | 9 | # Note that the version in the top level package.json gets updated 10 | # by the "@semantic-release/npm" so does not need to be dealt with here. 11 | 12 | # Update the version in the Python package 13 | sed -i -e "s!^ version=.*! version=\"$VERSION\",!" python/setup.py 14 | 15 | # Update the version in the R package 16 | sed -i -e "s!^Version:.*!Version: $VERSION!" r/DESCRIPTION 17 | 18 | # Update the version in the Rust crate (including lock file) 19 | sed -i -e "s!^version = .*!version = \"$VERSION\"!" rust/Cargo.toml 20 | (cd rust && cargo generate-lockfile) 21 | -------------------------------------------------------------------------------- /.ci/publish-docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bash functions for doing things as part of CI build 4 | 5 | checkout_pages() { 6 | git config --global user.email "ci@stenci.la" 7 | git config --global user.name "Stencila CI Bot" 8 | 9 | git remote add origin-pages https://${GITHUB_TOKEN}@github.com/stencila/schema.git > /dev/null 2>&1 10 | git fetch --all 11 | git checkout --force --track origin-pages/gh-pages 12 | git branch --set-upstream-to origin-pages/gh-pages 13 | git reset --hard 14 | } 15 | 16 | push_pages() { 17 | git push --quiet 18 | } 19 | 20 | commit_docs() { 21 | git add -f --all docs 22 | git commit --message "$1" 23 | } 24 | 25 | deploy_typescript_docs_to_pages() { 26 | checkout_pages 27 | cd ts 28 | commit_docs "docs(TypeScript): Update" 29 | push_pages 30 | } 31 | 32 | deploy_python_docs_to_pages() { 33 | checkout_pages 34 | cd python 35 | commit_docs "docs(Python): Update" 36 | push_pages 37 | } 38 | 39 | deploy_r_docs_to_pages() { 40 | checkout_pages 41 | cd r 42 | commit_docs "docs(R): Update" 43 | push_pages 44 | } 45 | 46 | # Call one of the functions as specified by the first arg 47 | $1 48 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Tell Docker to ignore all files apart from those absolutely needed to setup a 2 | # development environment. 3 | # For why this is a good idea see https://codefresh.io/docker-tutorial/not-ignore-dockerignore/ 4 | 5 | * 6 | 7 | !/Makefile 8 | !/package*.json 9 | 10 | !/python/Makefile 11 | !/python/requirements-dev.txt 12 | 13 | !/r/Makefile 14 | !/r/DESCRIPTION 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig file https://EditorConfig.org 2 | 3 | root = true 4 | 5 | # Default settings 6 | 7 | [*] 8 | indent_style = space 9 | indent_size = 2 10 | tab_width = 2 11 | end_of_line = lf 12 | charset = utf-8 13 | trim_trailing_whitespace = true 14 | insert_final_newline = true 15 | 16 | # Overrides for certain file types where necessary 17 | # to meet requirements or conventions. 18 | 19 | [*.py] 20 | indent_size = 4 21 | 22 | [Makefile] 23 | indent_style = tab 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | .Rproj.user 4 | *.out.* 5 | stencilaschema_*.tar.gz 6 | /coverage 7 | /dist 8 | /docs 9 | /node_modules 10 | /public 11 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/* 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | __file_snapshots__ 2 | .mypy_cache 3 | .tox 4 | .vscode/settings.json 5 | CHANGELOG.md 6 | CONTRIBUTING.md 7 | coverage 8 | dist 9 | docs 10 | node_modules 11 | package-lock.json 12 | public 13 | python/htmlcov 14 | README.md 15 | rust/target 16 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["redhat.vscode-yaml"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "node", 6 | "request": "launch", 7 | "name": "Jest All", 8 | "program": "${workspaceFolder}/node_modules/.bin/jest", 9 | "args": ["--runInBand"], 10 | "cwd": "${workspaceFolder}", 11 | "console": "integratedTerminal", 12 | "internalConsoleOptions": "neverOpen", 13 | "windows": { 14 | "program": "${workspaceFolder}/node_modules/jest/bin/jest" 15 | } 16 | }, 17 | { 18 | "type": "node", 19 | "request": "launch", 20 | "name": "Jest Current File", 21 | "program": "${workspaceFolder}/node_modules/.bin/jest", 22 | "args": ["${relativeFile}"], 23 | "cwd": "${workspaceFolder}", 24 | "console": "integratedTerminal", 25 | "internalConsoleOptions": "neverOpen", 26 | "windows": { 27 | "program": "${workspaceFolder}/node_modules/jest/bin/jest" 28 | } 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.10 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | RUN apt-get update \ 5 | && apt-get install -y \ 6 | curl \ 7 | && curl -sL https://deb.nodesource.com/setup_14.x | bash - \ 8 | && apt-get update \ 9 | && apt-get install -y \ 10 | libcurl4-openssl-dev \ 11 | libfontconfig1-dev \ 12 | libfreetype6-dev \ 13 | libgit2-dev \ 14 | libjpeg-dev \ 15 | libpng-dev \ 16 | libssh2-1-dev \ 17 | libssl-dev \ 18 | libtiff5-dev \ 19 | libxml2-dev \ 20 | nodejs \ 21 | pandoc \ 22 | python3 \ 23 | python3-pip \ 24 | r-base \ 25 | && rm -rf /var/lib/apt/lists/* 26 | 27 | COPY . /code 28 | WORKDIR /code 29 | 30 | # Install development dependencies for all languages 31 | RUN make setup 32 | 33 | # Run as non root user so that generated files do not require root 34 | # to delete or modify 35 | ARG USER_ID=1000 36 | ARG GROUP_ID=1000 37 | RUN groupadd --gid $GROUP_ID guest 38 | RUN useradd --uid $USER_ID -g $GROUP_ID guest 39 | USER guest 40 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # A Makefile for running high level development tasks. For finer 2 | # grained tasks see `package.json` and use `npm run `, or the 3 | # `Makefiles` for each language folder e.g. `python/Makefile`. 4 | 5 | all: format lint test build docs 6 | 7 | setup: 8 | npm install 9 | make -C python setup 10 | make -C r setup 11 | 12 | format: 13 | npm run format 14 | make -C rust format 15 | 16 | lint: 17 | npm run lint 18 | make -C python lint 19 | make -C r lint 20 | make -C rust lint 21 | 22 | test: 23 | npm test 24 | make -C python test 25 | make -C r test 26 | make -C rust test 27 | 28 | build: 29 | npm run build 30 | make -C python build 31 | make -C r build 32 | 33 | docs: 34 | npm run docs 35 | make -C python docs 36 | make -C r docs 37 | make -C rust docs 38 | .PHONY: docs 39 | 40 | clean: 41 | npm run clean 42 | make -C python clean 43 | make -C r clean 44 | make -C rust clean 45 | 46 | # Build Docker image for development 47 | build-image: 48 | docker build \ 49 | --build-arg USER_ID=$$(id -u) \ 50 | --build-arg GROUP_ID=$$(id -g) \ 51 | -t stencila/schema . 52 | 53 | # Run an interactive shell in Docker container 54 | run-image: 55 | docker run --rm -it -v $$PWD:/code -w /code stencila/schema bash 56 | -------------------------------------------------------------------------------- /examples/article.ts: -------------------------------------------------------------------------------- 1 | import { Article } from '../ts/types' 2 | 3 | export const minimal: Article = { 4 | type: 'Article', 5 | title: '', 6 | authors: [], 7 | } 8 | 9 | export const simple: Article = { 10 | type: 'Article', 11 | title: 'The title of this article', 12 | authors: [], 13 | } 14 | -------------------------------------------------------------------------------- /examples/article/complex.article.yaml: -------------------------------------------------------------------------------- 1 | type: Article 2 | title: Introducing eLife’s first computationally reproducible article 3 | url: https://elifesciences.org/labs/ad58f08d/introducing-elife-s-first-computationally-reproducible-article 4 | authors: 5 | - type: Person 6 | givenNames: 7 | - Giuliano 8 | familyNames: 9 | - Maciocci 10 | - type: Person 11 | givenNames: 12 | - Michael 13 | familyNames: 14 | - Aufreiter 15 | - type: Person 16 | givenNames: 17 | - Nokome 18 | familyNames: 19 | - Bentley 20 | content: 21 | - type: Paragraph 22 | content: 23 | - >- 24 | In September 2017 eLife announced the start of the Reproducible Document 25 | Stack (RDS) project, a collaboration between Substance, Stencila and 26 | eLife to support the development of an open-source technology stack 27 | aimed at enabling researchers to publish reproducible manuscripts 28 | through online journals. Reproducible manuscripts enrich the traditional 29 | narrative of a research article with code, data and interactive figures 30 | that can be executed in the browser, downloaded and explored, giving 31 | readers a direct insight into the methods, algorithms and key data 32 | behind the published research. 33 | - type: Paragraph 34 | content: 35 | - 'Today eLife, in collaboration with ' 36 | - type: Link 37 | target: 'http://substance.io/' 38 | content: 39 | - Substance 40 | - ', ' 41 | - type: Link 42 | target: 'https://stenci.la/' 43 | content: 44 | - Stencila 45 | - ' and Tim Errington, Director of Research ar the Center for Open Science, US, published its ' 46 | - type: Link 47 | target: 'https://elifesci.org/reproducible-example' 48 | content: 49 | - first reproducible article 50 | - >- 51 | , based on one of Errington’s papers in the Reproducibility Project: 52 | Cancer Biology. This reproducible version of the article showcases some 53 | of what’s possible with the new RDS tools, and we invite researchers to 54 | explore the newly available opportunities to tell their story. 55 | -------------------------------------------------------------------------------- /examples/article/simple.article.yaml: -------------------------------------------------------------------------------- 1 | type: Article 2 | title: Recherches sur les substances radioactives 3 | authors: 4 | - type: Person 5 | honorificPrefix: Dr 6 | givenNames: 7 | - Marie 8 | - Skłodowska 9 | familyNames: 10 | - Curie 11 | honorificSuffix: PhD 12 | -------------------------------------------------------------------------------- /examples/brand/simple.brand.yaml: -------------------------------------------------------------------------------- 1 | type: Brand 2 | logo: https://stenci.la/img/icons/stencil-machine.svg 3 | reviews: 4 | - 'Awful. Broke my computer and research.' 5 | -------------------------------------------------------------------------------- /examples/collection.invalid.yaml: -------------------------------------------------------------------------------- 1 | # Parts are required 2 | type: Collection 3 | -------------------------------------------------------------------------------- /examples/collection.ts: -------------------------------------------------------------------------------- 1 | import { Collection } from '../ts/types' 2 | import * as article from './article' 3 | import * as datatable from './datatable' 4 | 5 | export const minimal: Collection = { 6 | type: 'Collection', 7 | parts: [], 8 | } 9 | 10 | export const simple: Collection = { 11 | type: 'Collection', 12 | editors: [ 13 | { 14 | type: 'Person', 15 | }, 16 | ], 17 | publisher: { 18 | type: 'Organization', 19 | }, 20 | parts: [article.simple, datatable.minimal], 21 | } 22 | -------------------------------------------------------------------------------- /examples/collection.yaml: -------------------------------------------------------------------------------- 1 | # An empty collection 2 | type: Collection 3 | parts: [] 4 | 5 | --- 6 | # A simple collection with just one article 7 | type: Collection 8 | parts: 9 | - type: Article 10 | title: Article one 11 | authors: 12 | - type: Person 13 | 14 | --- 15 | # A collection with editors etc 16 | type: Collection 17 | editors: 18 | - type: Person 19 | name: John Johnston 20 | - type: Person 21 | name: Janes Jones 22 | parts: 23 | - type: Article 24 | title: Article one 25 | authors: 26 | - type: Person 27 | -------------------------------------------------------------------------------- /examples/contactPoint/simple.ContactPoint.yaml: -------------------------------------------------------------------------------- 1 | type: ContactPoint 2 | availableLanguages: 3 | - 'English' 4 | - 'French' 5 | emails: 6 | - 'english@email.com' 7 | - 'french@email.com' 8 | telephone: '+649775673' 9 | -------------------------------------------------------------------------------- /examples/datatable.ts: -------------------------------------------------------------------------------- 1 | import { Datatable } from '../ts/types' 2 | 3 | export const minimal: Datatable = { 4 | type: 'Datatable', 5 | columns: [], 6 | } 7 | -------------------------------------------------------------------------------- /examples/datatables/simple.datatable.yaml: -------------------------------------------------------------------------------- 1 | type: Datatable 2 | columns: 3 | - type: DatatableColumn 4 | name: A 5 | schema: 6 | type: DatatableColumnSchema 7 | items: 8 | type: number 9 | values: 10 | - 1 11 | - 2 12 | - 3 13 | - type: DatatableColumn 14 | name: B 15 | values: 16 | - 4 17 | - 5 18 | - 6 19 | -------------------------------------------------------------------------------- /examples/emphasis/invalid.emphasis.yaml: -------------------------------------------------------------------------------- 1 | type: Emphasis 2 | content: 3 | - type: Paragraph 4 | -------------------------------------------------------------------------------- /examples/emphasis/simple.emphasis.yaml: -------------------------------------------------------------------------------- 1 | type: Emphasis 2 | content: 3 | - Some emphasied text 4 | -------------------------------------------------------------------------------- /examples/heading/invalid.heading.yaml: -------------------------------------------------------------------------------- 1 | type: Heading 2 | # Missing property "depth". 3 | depths: 1 4 | # Property depths is not allowed. 5 | content: 6 | - type: Heading 7 | content: 8 | - type: Text 9 | value: bar 10 | -------------------------------------------------------------------------------- /examples/heading/simple.heading.yaml: -------------------------------------------------------------------------------- 1 | type: Heading 2 | depth: 1 3 | content: 4 | - Metamorphosis 5 | -------------------------------------------------------------------------------- /examples/imageObjects/invalid.imageObject.yaml: -------------------------------------------------------------------------------- 1 | type: ImageObject 2 | contentUrl: example.com/image.png 3 | # String is not a URI: URI with a scheme is expected. 4 | caption: 42 5 | # Incorrect type. Expected "string". 6 | -------------------------------------------------------------------------------- /examples/imageObjects/simple.imageObject.yaml: -------------------------------------------------------------------------------- 1 | type: ImageObject 2 | contentUrl: http://example.com/image.png 3 | caption: My photo 4 | -------------------------------------------------------------------------------- /examples/invalid/invalid.brand.yaml: -------------------------------------------------------------------------------- 1 | type: Brand 2 | logo: 3 | 42 4 | # Incorrect type. Expected a URI. 5 | reviews: 6 | - [] 7 | # Incorrect type. Expected "string". 8 | -------------------------------------------------------------------------------- /examples/invalid/invalid.contactPoint.yaml: -------------------------------------------------------------------------------- 1 | type: ContactPoint 2 | availableLanguages: 675 3 | # Incorrect type. Expected "array". 4 | emails: 5 | - 22 6 | # Incorrect type. Expected "string". 7 | - _email 8 | # String is not an e-mail address. 9 | telephone: 897364 10 | # Incorrect type. "Expected string" matching pattern '\+\d*[0-9]'. 11 | -------------------------------------------------------------------------------- /examples/invalid/invalid.organization.yaml: -------------------------------------------------------------------------------- 1 | type: Organization 2 | address: 3 | - '12 Random Road, Random Town, Aotearoa' 4 | # Incorrect type. Expected "string". 5 | brands: 6 | - logo: 7 | - https://stenci.la/img/icons/stencil-machine.svg 8 | review: 4567 9 | contactPoints: 10 | - type: ContactPoint 11 | availableLanguages: 'English' 12 | email: 'english@email.com' 13 | telephone: (00)64-9775673 14 | departments: Computer Science 15 | # Incorrect type. Expected "array". 16 | emails: 17 | - mailto:organization@organization.com 18 | # Property emails is not allowed. 19 | funders: 20 | - simple.person.yaml 21 | # Incorrect type. Expected "object". 22 | legalName: _o6794-7485 23 | #String does not match the pattern of '[a-zA-Z]'. 24 | -------------------------------------------------------------------------------- /examples/link/simple.link.yaml: -------------------------------------------------------------------------------- 1 | type: Link 2 | content: 3 | - Stencila’s website 4 | target: https://stenci.la 5 | -------------------------------------------------------------------------------- /examples/link/withRelationship.link.yaml: -------------------------------------------------------------------------------- 1 | type: Link 2 | content: 3 | - Stencila’s website 4 | target: https://stenci.la 5 | relation: external 6 | -------------------------------------------------------------------------------- /examples/list/nested.list.yaml: -------------------------------------------------------------------------------- 1 | type: List 2 | items: 3 | - type: ListItem 4 | content: 5 | - Item One 6 | - type: ListItem 7 | content: 8 | - Item Two, containing nested children 9 | - type: List 10 | items: 11 | - type: ListItem 12 | content: 13 | - Nested Item One 14 | - type: ListItem 15 | content: 16 | - Nested Item Two 17 | - type: ListItem 18 | content: 19 | - Nested Item Three 20 | - type: ListItem 21 | content: 22 | - Item Three 23 | -------------------------------------------------------------------------------- /examples/list/simple.list.yaml: -------------------------------------------------------------------------------- 1 | type: List 2 | items: 3 | - type: ListItem 4 | content: 5 | - Item One 6 | - type: ListItem 7 | content: 8 | - Item Two 9 | - type: ListItem 10 | content: 11 | - Item Three 12 | -------------------------------------------------------------------------------- /examples/listItem/nested.listItem.yaml: -------------------------------------------------------------------------------- 1 | type: ListItem 2 | content: 3 | # Nodes in list item `content` must be `BlockContent` nodes 4 | - type: Paragraph 5 | content: 6 | - Item Two, containing nested children 7 | - type: List 8 | items: 9 | # Items in a lis can be any `Node` type 10 | - Nested Item One 11 | - Nested Item Two 12 | - Nested Item Three 13 | -------------------------------------------------------------------------------- /examples/listItem/simple.listItem.yaml: -------------------------------------------------------------------------------- 1 | type: ListItem 2 | content: 3 | # Nodes in list item `content` must be `BlockContent` nodes 4 | - type: Paragraph 5 | content: 6 | - Item One 7 | - type: Paragraph 8 | content: 9 | - Item Two 10 | - type: Paragraph 11 | content: 12 | - Item Three 13 | -------------------------------------------------------------------------------- /examples/mediaObject.yaml: -------------------------------------------------------------------------------- 1 | # Format specified as media type 2 | type: MediaObject 3 | contentUrl: https://example.org/page.html 4 | format: text/html 5 | 6 | --- 7 | # Format specified as an extension name 8 | type: MediaObject 9 | contentUrl: https://example.org/page.html 10 | format: html 11 | -------------------------------------------------------------------------------- /examples/organization/simple.organization.yaml: -------------------------------------------------------------------------------- 1 | type: Organization 2 | address: '12 Random Road, Random Town, Aotearoa' 3 | brands: 4 | - type: Brand 5 | logo: https://stenci.la/img/icons/stencil-machine.svg 6 | reviews: 7 | - 'Awful. Broke my computer and research.' 8 | contactPoints: 9 | - type: ContactPoint 10 | availableLanguages: 11 | - 'English' 12 | - 'French' 13 | emails: 14 | - 'english@email.com' 15 | - 'french@email.com' 16 | telephone: '+649775673' 17 | departments: 18 | - type: Organization 19 | funders: 20 | - type: Person 21 | givenNames: 22 | - John 23 | - Tom 24 | familyNames: 25 | - Smith 26 | emails: 27 | - john.smith@example.com 28 | honorificPrefix: Dr 29 | legalName: University of Life 30 | -------------------------------------------------------------------------------- /examples/paragraph/invalid.paragraph.yaml: -------------------------------------------------------------------------------- 1 | type: Paragraph 2 | content: 3 | - type: Paragraph 4 | content: 5 | - This paragraph should not be here 6 | -------------------------------------------------------------------------------- /examples/paragraph/nested.paragraph.yaml: -------------------------------------------------------------------------------- 1 | type: Paragraph 2 | content: 3 | - Some text with some 4 | - type: Emphasis 5 | content: 6 | - emphasised words 7 | - ' and ' 8 | - type: Strong 9 | content: 10 | - some strongly emphasised words 11 | -------------------------------------------------------------------------------- /examples/paragraph/simple.paragraph.yaml: -------------------------------------------------------------------------------- 1 | type: Paragraph 2 | content: 3 | - Some text content representing ideas expressed as words. 4 | -------------------------------------------------------------------------------- /examples/product/simple.product.yaml: -------------------------------------------------------------------------------- 1 | type: Product 2 | brand: 3 | type: Brand 4 | logo: https://stenci.la/img/icons/stencil-machine.svg 5 | reviews: 6 | - 'Awful. Broke my computer and research.' 7 | productID: 675ef78 8 | -------------------------------------------------------------------------------- /examples/quote/attributed.quote.yaml: -------------------------------------------------------------------------------- 1 | type: Quote 2 | content: 3 | - 'If you wish to make an apple pie from scratch, you must first invent the universe. — Carl Sagan - Cosmos' 4 | citation: 'https://www.goodreads.com/quotes/32952-if-you-wish-to-make-an-apple-pie-from-scratch' 5 | -------------------------------------------------------------------------------- /examples/quote/simple.quote.yaml: -------------------------------------------------------------------------------- 1 | type: Quote 2 | content: 3 | - 'If you wish to make an apple pie from scratch, you must first invent the universe. — Carl Sagan - Cosmos' 4 | -------------------------------------------------------------------------------- /examples/quoteBlock/attributed.quoteBlock.yaml: -------------------------------------------------------------------------------- 1 | type: QuoteBlock 2 | content: 3 | - type: Paragraph 4 | content: 5 | - 'If you wish to make an apple pie from scratch, you must first invent the universe.' 6 | - 'by Carl Sagan — Cosmos' 7 | citation: 'https://www.goodreads.com/quotes/32952-if-you-wish-to-make-an-apple-pie-from-scratch' 8 | -------------------------------------------------------------------------------- /examples/quoteBlock/simple.quoteBlock.yaml: -------------------------------------------------------------------------------- 1 | type: QuoteBlock 2 | content: 3 | - type: Paragraph 4 | content: 5 | - 'If you wish to make an apple pie from scratch, you must first invent the universe.' 6 | - 'by Carl Sagan - Cosmos' 7 | -------------------------------------------------------------------------------- /examples/software/invalid.softwareApplication.yaml: -------------------------------------------------------------------------------- 1 | type: SoftwareApplication 2 | softwareRequirements: 3 | # Invalid - Just a list of strings 4 | - Some Package 5 | - Some Other Package 6 | -------------------------------------------------------------------------------- /examples/software/invalid.softwareSession.yaml: -------------------------------------------------------------------------------- 1 | type: SoftwareSession 2 | # Missing property "environment". 3 | cpuResource: 4 | type: ResourceParameters 5 | # Invalid, requested must be > 0 6 | requested: -1 7 | # Invalid, limit but be > 0 8 | limit: -2 9 | -------------------------------------------------------------------------------- /examples/software/invalid.softwareSourceCode.yaml: -------------------------------------------------------------------------------- 1 | type: SoftwareSourceCode 2 | maintainers: 3 | # invalid, should be People or Organizations not just strings 4 | - Joe Smith 5 | - Jane Doe 6 | 7 | # String is not a URI: URI with a scheme is expected. 8 | codeRepository: my-repo.git 9 | -------------------------------------------------------------------------------- /examples/software/simple.softwareApplication.yaml: -------------------------------------------------------------------------------- 1 | type: SoftwareApplication 2 | softwareRequirements: 3 | - type: SoftwareApplication 4 | name: SomePackage 5 | softwareVersion: 1.2.3 6 | - type: SoftwareApplication 7 | name: SomeOtherPackage 8 | softwareVersion: 3.2.1 9 | -------------------------------------------------------------------------------- /examples/software/simple.softwareSession.yaml: -------------------------------------------------------------------------------- 1 | type: SoftwareSession 2 | environment: 3 | type: Environment 4 | name: StencilaMega 5 | volumeMounts: 6 | - type: Mount 7 | mountSource: /foo/bar 8 | mountDestination: /baz/bax 9 | cpuResource: 10 | type: ResourceParameters 11 | resourceRequested: 500 12 | resourceLimit: 1000 13 | memoryResource: 14 | type: ResourceParameters 15 | resourceRequested: 1024 16 | resourceLimit: 2048 17 | -------------------------------------------------------------------------------- /examples/software/simple.softwareSourceCode.yaml: -------------------------------------------------------------------------------- 1 | type: SoftwareSourceCode 2 | codeRepository: https://github.com/stencila/schema 3 | -------------------------------------------------------------------------------- /examples/strong/nested.strong.yaml: -------------------------------------------------------------------------------- 1 | type: Strong 2 | content: 3 | - 'Some ' 4 | - type: Delete 5 | content: 6 | - 'important' 7 | - 'essential information' 8 | -------------------------------------------------------------------------------- /examples/strong/simple.strong.yaml: -------------------------------------------------------------------------------- 1 | type: Strong 2 | content: 3 | - 'Some important information' 4 | -------------------------------------------------------------------------------- /examples/table/header.table.yaml: -------------------------------------------------------------------------------- 1 | # Recreates the headers and first two rows from 2 | # https://www.w3.org/WAI/tutorials/tables/two-headers/#table-with-header-cells-in-the-top-row-and-first-column 3 | type: Table 4 | rows: 5 | - type: TableRow 6 | kind: header 7 | cells: 8 | - type: TableCell 9 | content: 10 | - Monday 11 | - type: TableCell 12 | content: 13 | - Tuesday 14 | - type: TableCell 15 | content: 16 | - Wednesday 17 | - type: TableCell 18 | content: 19 | - Thursday 20 | - type: TableCell 21 | content: 22 | - Friday 23 | - type: TableRow 24 | cells: 25 | - type: TableCell 26 | kind: header 27 | content: 28 | - '09:00 - 11:00' 29 | - type: TableCell 30 | content: 31 | - Closed 32 | - type: TableCell 33 | content: 34 | - Open 35 | - type: TableCell 36 | content: 37 | - Open 38 | - type: TableCell 39 | content: 40 | - Closed 41 | - type: TableCell 42 | content: 43 | - Closed 44 | - type: TableRow 45 | cells: 46 | - type: TableCell 47 | kind: header 48 | content: 49 | - '11:00 - 13:00' 50 | - type: TableCell 51 | content: 52 | - Open 53 | - type: TableCell 54 | content: 55 | - Open 56 | - type: TableCell 57 | content: 58 | - Closed 59 | - type: TableCell 60 | content: 61 | - Closed 62 | - type: TableCell 63 | content: 64 | - Closed 65 | -------------------------------------------------------------------------------- /examples/table/irregularHeader.table.yaml: -------------------------------------------------------------------------------- 1 | # Recreates the table from 2 | # https://www.w3.org/WAI/tutorials/tables/irregular/#table-with-two-tier-headers 3 | type: Table 4 | rows: 5 | - type: TableRow 6 | cells: 7 | - type: TableCell 8 | rowspan: 2 9 | content: [] 10 | - type: TableCell 11 | kind: header 12 | colspan: 2 13 | content: 14 | - Mars 15 | - type: TableCell 16 | kind: header 17 | colspan: 2 18 | content: 19 | - Venus 20 | - type: TableRow 21 | cells: 22 | - type: TableCell 23 | content: 24 | - Produced 25 | - type: TableCell 26 | kind: header 27 | content: 28 | - Sold 29 | - type: TableRow 30 | cells: 31 | - type: TableCell 32 | content: 33 | - Produced 34 | - type: TableCell 35 | kind: header 36 | content: 37 | - Sold 38 | - type: TableRow 39 | cells: 40 | - type: TableCell 41 | kind: header 42 | content: 43 | - Teddy Bears 44 | - type: TableCell 45 | content: 46 | - 50,000 47 | - type: TableCell 48 | content: 49 | - 30,000 50 | - type: TableCell 51 | content: 52 | - 100,000 53 | - type: TableCell 54 | content: 55 | - 80,000 56 | - type: TableRow 57 | cells: 58 | - type: TableCell 59 | kind: header 60 | content: 61 | - Board Games 62 | - type: TableCell 63 | content: 64 | - 10,000 65 | - type: TableCell 66 | content: 67 | - 5,000 68 | - type: TableCell 69 | content: 70 | - 12,000 71 | - type: TableCell 72 | content: 73 | - 9,000 74 | -------------------------------------------------------------------------------- /examples/table/simple.table.yaml: -------------------------------------------------------------------------------- 1 | type: Table 2 | rows: 3 | - type: TableRow 4 | cells: 5 | - type: TableCell 6 | content: 7 | - 1 8 | - type: TableCell 9 | content: 10 | - 2 11 | -------------------------------------------------------------------------------- /examples/tableCell/allProperties.tableCell.yaml: -------------------------------------------------------------------------------- 1 | type: TableCell 2 | name: myCustomLabel 3 | content: 4 | - 1 5 | colspan: 2 6 | rowspan: 1 7 | -------------------------------------------------------------------------------- /examples/tableCell/inlineContent.tableCell.yaml: -------------------------------------------------------------------------------- 1 | type: TableCell 2 | content: 3 | - type: Emphasis 4 | content: 5 | - Some emphasized Content 6 | -------------------------------------------------------------------------------- /examples/tableCell/simple.tableCell.yaml: -------------------------------------------------------------------------------- 1 | type: TableCell 2 | content: 3 | - 1 4 | -------------------------------------------------------------------------------- /examples/tableRow/multipleRows.tableRow.yaml: -------------------------------------------------------------------------------- 1 | type: TableRow 2 | cells: 3 | - type: TableCell 4 | content: 5 | - 1 6 | - type: TableCell 7 | content: 8 | - 2 9 | - type: TableCell 10 | content: 11 | - 3 12 | -------------------------------------------------------------------------------- /examples/tableRow/simple.tableRow.yaml: -------------------------------------------------------------------------------- 1 | type: TableRow 2 | cells: 3 | - type: TableCell 4 | content: 5 | - 1 6 | -------------------------------------------------------------------------------- /examples/thematicBreak/simple.thematicBreak.yaml: -------------------------------------------------------------------------------- 1 | type: ThematicBreak 2 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | # Redirect from /latest to root 2 | 3 | [[redirects]] 4 | from = "/latest/*" 5 | to = "/:splat" 6 | 7 | # The recommended way to serve JSON-LD is with "Cool URIs" 8 | # and content negotiation. eg. this is how schema.org does it: 9 | # curl http://schema.org/Person -H "Accept:application/ld+json" -i 10 | # Netlify does not support content negotiation 11 | # (i.e. redirects based on the Accept header) 12 | # Therefore, to provide a URL that fits with 13 | # the norms for JSON-LD (no file extensions), 14 | # we need to provide a specific route. 15 | 16 | [[redirects]] 17 | from = "/jsonld" 18 | to = "/stencila.jsonld" 19 | 20 | [[redirects]] 21 | from = "/jsonld/*" 22 | to = "/:splat.jsonld" 23 | 24 | # Redirect to unpkg 25 | # Why? Because for the version redirects below 26 | # unpkg redirects to an expanded, but relative, URL 27 | # which Netlify thinks it should serve e.g: 28 | # > curl --silent --head https://unpkg.com/@stencila/schema@0/dist/CodeChunk.schema.json | grep Location 29 | # Location: /@stencila/schema@0.32.3/dist/CodeChunk.schema.json 30 | # So this redirects back to unpkg: 31 | [[redirects]] 32 | from = "/@stencila/*" 33 | to = "https://unpkg.com/@stencila/:splat" 34 | force = true 35 | 36 | # Version redirects 37 | # These redirect intentionally use http, instead of https, 38 | # because that causes 39 | # Unfortunately, given the current URL pattern `v1` etc, 40 | # we can't make this work using placeholders 41 | # (i.e. using `v:number`; placeholders must come after a slash). 42 | # So more redirects for new versions will need to be added in 43 | # the future. 44 | 45 | [[redirects]] 46 | from = "/v0/jsonld" 47 | to = "https://unpkg.com/@stencila/schema@0/dist/stencila.jsonld" 48 | force = true 49 | 50 | [[redirects]] 51 | from = "/v0/jsonld/*" 52 | to = "https://unpkg.com/@stencila/schema@0/dist/:splat.jsonld" 53 | force = true 54 | 55 | [[redirects]] 56 | from = "/v0/*" 57 | to = "https://unpkg.com/@stencila/schema@0/dist/:splat" 58 | force = true 59 | 60 | [[redirects]] 61 | from = "/v1/jsonld" 62 | to = "https://unpkg.com/@stencila/schema@1/dist/stencila.jsonld" 63 | force = true 64 | 65 | [[redirects]] 66 | from = "/v1/jsonld/*" 67 | to = "https://unpkg.com/@stencila/schema@1/dist/:splat.jsonld" 68 | force = true 69 | 70 | [[redirects]] 71 | from = "/v1/*" 72 | to = "https://unpkg.com/@stencila/schema@1/dist/:splat" 73 | force = true 74 | 75 | # Redirect content not found here to https://help.stenci.la/references/schema 76 | # This is primarily intended for documentation e.g. 77 | # https://schema.stenci.la/CodeChunk -> https://help.stenci.la/references/schema/CodeChunk 78 | 79 | [[redirects]] 80 | from = "/*" 81 | to = "https://help.stenci.la/references/schema/:splat" 82 | -------------------------------------------------------------------------------- /python/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .coverage 3 | .DS_Store 4 | .idea 5 | .mypy_cache 6 | .tox 7 | *.egg-info 8 | build 9 | coverage.xml 10 | dist 11 | docs 12 | htmlcov 13 | version 14 | -------------------------------------------------------------------------------- /python/.mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | ignore_missing_imports = True 3 | pretty = True 4 | -------------------------------------------------------------------------------- /python/.pylintrc: -------------------------------------------------------------------------------- 1 | [FORMAT] 2 | 3 | max-line-length=120 4 | 5 | [MASTER] 6 | 7 | ignore-patterns=types.py 8 | -------------------------------------------------------------------------------- /python/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md LICENSE version 2 | -------------------------------------------------------------------------------- /python/Makefile: -------------------------------------------------------------------------------- 1 | all: regen lint format test build docs 2 | 3 | setup: 4 | pip3 install -r requirements-dev.txt 5 | 6 | install: 7 | python3 setup.py install 8 | 9 | regen: 10 | npm run build:python 11 | 12 | lint: 13 | python3 -m pylint stencila/schema 14 | python3 -m mypy stencila/schema --config-file .mypy.ini 15 | 16 | format: 17 | python3 -m black --exclude stencila/schema/types.py ./stencila ./*.py 18 | 19 | test: 20 | python3 -m tox 21 | 22 | build: 23 | python3 setup.py sdist bdist_wheel 24 | .PHONY: build 25 | 26 | docs: 27 | python3 -m pdoc --html --output-dir docs --force ./stencila/schema 28 | mv docs/schema/* docs 29 | rmdir docs/schema 30 | .PHONY: docs 31 | 32 | clean: 33 | rm -rf build dist .mypy_cache .coverage coverage.xml htmlcov .tox *.egg-info **/__pycache__ 34 | -------------------------------------------------------------------------------- /python/requirements-dev.txt: -------------------------------------------------------------------------------- 1 | black==19.10b0 2 | mypy==0.761 3 | pdoc3==0.7.4 4 | pylint==2.4.4 5 | tox==3.14.3 6 | twine==3.1.1 7 | wheel==0.35.1 8 | -------------------------------------------------------------------------------- /python/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | 6 | import io 7 | import os 8 | from setuptools import setup, Command 9 | from shutil import rmtree 10 | 11 | HERE = os.path.abspath(os.path.dirname(__file__)) 12 | 13 | with io.open(os.path.join(HERE, "README.md"), encoding="utf-8") as f: 14 | long_description = "\n" + f.read() 15 | 16 | 17 | class UploadCommand(Command): 18 | """ 19 | Support setup.py upload. 20 | 21 | Based on, and thanks to, https://github.com/kennethreitz/setup.py/blob/master/setup.py 22 | """ 23 | 24 | description = "Build and publish the package." 25 | user_options = [] 26 | 27 | @staticmethod 28 | def status(s): 29 | """Prints things in bold.""" 30 | print("\033[1m{0}\033[0m".format(s)) 31 | 32 | def initialize_options(self): 33 | pass 34 | 35 | def finalize_options(self): 36 | pass 37 | 38 | def run(self): 39 | try: 40 | self.status("Removing previous builds…") 41 | rmtree(os.path.join(HERE, "dist")) 42 | except OSError: 43 | pass 44 | 45 | self.status("Building Source and Wheel (universal) distribution…") 46 | os.system("{0} setup.py sdist bdist_wheel --universal".format(sys.executable)) 47 | 48 | self.status("Uploading the package to PyPI via Twine…") 49 | 50 | repo_arg = ( 51 | "--repository-url https://test.pypi.org/legacy/" 52 | if os.environ.get("PYPI_ENV") == "test" 53 | else "" 54 | ) 55 | 56 | os.system("twine upload {} dist/*".format(repo_arg)) 57 | 58 | sys.exit() 59 | 60 | 61 | setup( 62 | name="stencila-schema", 63 | version="1.16.1", 64 | description="", 65 | long_description=long_description, 66 | long_description_content_type="text/markdown", 67 | author="Stencila and contributors", 68 | author_email="hello@stenci.la", 69 | python_requires=">=3.6.0", 70 | url="https://github.com/stencila/schema", 71 | packages=["stencila.schema"], 72 | extras_require={}, 73 | include_package_data=True, 74 | license="Apache-2.0", 75 | classifiers=[ 76 | "License :: OSI Approved :: Apache Software License", 77 | "Programming Language :: Python", 78 | "Programming Language :: Python :: 3", 79 | "Programming Language :: Python :: 3.6", 80 | "Programming Language :: Python :: Implementation :: CPython", 81 | "Programming Language :: Python :: Implementation :: PyPy", 82 | ], 83 | cmdclass={"upload": UploadCommand,}, 84 | ) 85 | -------------------------------------------------------------------------------- /python/stencila/schema/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | .. include:: ../../README.md 3 | """ 4 | -------------------------------------------------------------------------------- /python/stencila/schema/json.py: -------------------------------------------------------------------------------- 1 | """ 2 | Functions for converting nodes to/from JSON. 3 | 4 | This is a JSON "codec" analogous to that in 5 | [Encoda](https://github.com/stencila/encoda/blob/v0.85.3/src/codecs/json/index.ts) 6 | which provides `encode` and `decode` functions to/from JSON and Python 7 | objects representing Schema nodes. 8 | """ 9 | import json 10 | import typing 11 | 12 | from . import types 13 | from .types import Node, Entity 14 | 15 | 16 | def decode(serialized: str) -> Node: 17 | """Decode JSON as a `Node`""" 18 | node = json.loads(serialized) 19 | return dict_decode(node) if isinstance(node, dict) else node 20 | 21 | 22 | def encode(node: Node) -> str: 23 | """Encode a `Node` to JSON""" 24 | return json.dumps(node, default=object_encode, indent=2) 25 | 26 | 27 | def dict_decode(node_dict: dict) -> Node: 28 | """Convert a dictionary to an `Entity` node (if it has a `type` item).""" 29 | if "type" not in node_dict: 30 | return node_dict 31 | 32 | node_type = node_dict.pop("type") 33 | class_ = getattr(types, node_type, None) 34 | 35 | if class_ is None: 36 | return node_dict 37 | 38 | node_kwargs = {} 39 | 40 | for key, val in node_dict.items(): 41 | if isinstance(val, dict): 42 | val = dict_decode(val) 43 | elif isinstance(val, list): 44 | processed_list = [] 45 | for sub_val in val: 46 | if isinstance(sub_val, dict): 47 | processed_list.append(dict_decode(sub_val)) 48 | else: 49 | processed_list.append(sub_val) 50 | val = processed_list 51 | 52 | node_kwargs[key] = val 53 | 54 | return class_(**node_kwargs) 55 | 56 | 57 | def object_encode(node: typing.Any) -> typing.Union[dict, str]: 58 | """Convert an `Entity` node to a dictionary""" 59 | if not isinstance(node, Entity): 60 | return str(node) 61 | 62 | node_dict = {"type": node.__class__.__name__} 63 | node_dict.update(node.__dict__) 64 | return node_dict 65 | -------------------------------------------------------------------------------- /python/stencila/schema/util.py: -------------------------------------------------------------------------------- 1 | """Utility functions.""" 2 | 3 | 4 | def node_type(node) -> str: 5 | """ 6 | Get the type of the node. 7 | 8 | This is the Python equivalent of the 9 | [`nodeType`](https://github.com/stencila/schema/blob/bd90c808d14136c8489ce8bb945b2bb6085b9356/ts/util/nodeType.ts) 10 | function. 11 | """ 12 | # pylint: disable=R0911 13 | 14 | if node is None: 15 | return "Null" 16 | if isinstance(node, bool): 17 | return "Boolean" 18 | if isinstance(node, (int, float)): 19 | return "Number" 20 | if isinstance(node, str): 21 | return "Text" 22 | if isinstance(node, (list, tuple)): 23 | return "Array" 24 | if isinstance(node, dict): 25 | type_name = node.get("type") 26 | if type_name is not None: 27 | return type_name 28 | return "Object" 29 | -------------------------------------------------------------------------------- /python/tests/test_article.py: -------------------------------------------------------------------------------- 1 | def test_article_example(): 2 | """Test to check that README example runs""" 3 | 4 | from stencila.schema.types import Article, Person 5 | from stencila.schema.json import encode 6 | 7 | encode( 8 | Article( 9 | title="The Impact of Interactive Epistemologies on Cryptography", 10 | authors=[ 11 | Person(givenNames=["Josiah", "Stinkney"], familyNames=["Carberry"]) 12 | ], 13 | ) 14 | ) 15 | -------------------------------------------------------------------------------- /python/tests/test_util.py: -------------------------------------------------------------------------------- 1 | from stencila.schema.util import node_type 2 | 3 | def test_node_type(): 4 | assert node_type(None) == "Null" 5 | assert node_type(True) == "Boolean" 6 | assert node_type(42) == "Number" 7 | assert node_type(3.14) == "Number" 8 | assert node_type("Hello") == "Text" 9 | assert node_type([]) == "Array" 10 | assert node_type(tuple()) == "Array" 11 | assert node_type({}) == "Object" 12 | assert node_type({"type": "CodeChunk"}) == "CodeChunk" 13 | -------------------------------------------------------------------------------- /python/tox.ini: -------------------------------------------------------------------------------- 1 | [testenv] 2 | deps = pytest 3 | pytest-cov 4 | coverage 5 | commands = pytest --cov {envsitepackagesdir}/stencila --cov-report term --cov-report xml --cov-report html tests 6 | 7 | [pytest] 8 | python_files = tests/test_*.py 9 | 10 | [coverage:run] 11 | omit = */schema/types.py 12 | -------------------------------------------------------------------------------- /r/.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^_pkgdown.yml$ 2 | ^.*\.Rproj$ 3 | ^.covrignore$ 4 | ^.lintr$ 5 | ^\.Rproj\.user$ 6 | ^docs$ 7 | ^Makefile$ -------------------------------------------------------------------------------- /r/.covrignore: -------------------------------------------------------------------------------- 1 | R/types.R 2 | -------------------------------------------------------------------------------- /r/.gitignore: -------------------------------------------------------------------------------- 1 | *.Rcheck 2 | *.Rhistory 3 | *.Rproj.user 4 | docs 5 | man 6 | -------------------------------------------------------------------------------- /r/.lintr: -------------------------------------------------------------------------------- 1 | linters: with_defaults(line_length_linter(120), object_usage_linter=NULL, object_name_linter(c("snake_case", "CamelCase"))) 2 | exclusions: list("R/types.R") 3 | -------------------------------------------------------------------------------- /r/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: stencilaschema 2 | Title: Bindings for Stencila Schema 3 | Description: Provides R bindings for the Stencila Schema . This package is primarily aimed at R developers wanting to programmatically generate, or modify, executable documents. 4 | Authors@R: c( 5 | person("Nokome", "Bentley", email = "nokome@stenci.la", role = c("aut", "cre")) 6 | ) 7 | URL: https://github.com/stencila/schema#readme 8 | BugReports: https://github.com/stencila/schema/issues 9 | License: Apache License (>= 2) 10 | Language: en-gb 11 | Version: 1.16.1 12 | Encoding: UTF-8 13 | Suggests: 14 | covr, 15 | devtools, 16 | lintr, 17 | pkgdown, 18 | rhub, 19 | roxygen2, 20 | spelling, 21 | testthat 22 | Roxygen: list(markdown = TRUE) 23 | RoxygenNote: 7.1.2 24 | Collate: 25 | 'typing.R' 26 | 'types.R' 27 | -------------------------------------------------------------------------------- /r/Makefile: -------------------------------------------------------------------------------- 1 | all: regen lint test build docs 2 | 3 | setup: 4 | Rscript -e "install.packages('devtools'); devtools::install_dev_deps()" 5 | 6 | regen: 7 | npm run build:r 8 | 9 | lint: 10 | Rscript -e 'lintr::lint_package()' 11 | 12 | test: 13 | Rscript -e 'devtools::test()' 14 | 15 | autotest: 16 | Rscript -e 'testthat::auto_test_package()' 17 | 18 | cover: 19 | Rscript -e 'covr::package_coverage()' 20 | 21 | check: 22 | Rscript -e 'devtools::check()' 23 | 24 | build: 25 | Rscript -e 'devtools::document(); warnings()' 26 | Rscript -e 'devtools::build()' 27 | 28 | docs: 29 | Rscript -e 'devtools::document(); pkgdown::build_site()' 30 | .PHONY: docs 31 | 32 | install: build 33 | Rscript -e 'devtools::install()' 34 | 35 | release: clean regen build 36 | Rscript -e 'devtools::check()' 37 | Rscript -e 'devtools::spell_check()' 38 | Rscript -e 'devtools::check_rhub()' 39 | Rscript -e 'devtools::check_win_devel()' 40 | 41 | clean: 42 | rm -rf man stencilaschema_*.tar.gz stencilaschema.Rcheck 43 | -------------------------------------------------------------------------------- /r/NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(Any) 4 | export(Array) 5 | export(ArrayValidator) 6 | export(Article) 7 | export(AudioObject) 8 | export(BlockContent) 9 | export(BooleanValidator) 10 | export(Brand) 11 | export(CitationIntentEnumeration) 12 | export(Cite) 13 | export(CiteGroup) 14 | export(Claim) 15 | export(Code) 16 | export(CodeBlock) 17 | export(CodeChunk) 18 | export(CodeError) 19 | export(CodeExecutable) 20 | export(CodeExecutableTypes) 21 | export(CodeExpression) 22 | export(CodeFragment) 23 | export(CodeTypes) 24 | export(Collection) 25 | export(Comment) 26 | export(ConstantValidator) 27 | export(ContactPoint) 28 | export(ContactPointTypes) 29 | export(CreativeWork) 30 | export(CreativeWorkTypes) 31 | export(Datatable) 32 | export(DatatableColumn) 33 | export(Date) 34 | export(DefinedTerm) 35 | export(Delete) 36 | export(Emphasis) 37 | export(Entity) 38 | export(EntityTypes) 39 | export(Enum) 40 | export(EnumValidator) 41 | export(Enumeration) 42 | export(EnumerationTypes) 43 | export(Figure) 44 | export(Function) 45 | export(Grant) 46 | export(GrantTypes) 47 | export(Heading) 48 | export(ImageObject) 49 | export(Include) 50 | export(InlineContent) 51 | export(IntegerValidator) 52 | export(Link) 53 | export(List) 54 | export(ListItem) 55 | export(Mark) 56 | export(MarkTypes) 57 | export(Math) 58 | export(MathBlock) 59 | export(MathFragment) 60 | export(MathTypes) 61 | export(MediaObject) 62 | export(MediaObjectTypes) 63 | export(MonetaryGrant) 64 | export(Node) 65 | export(NontextualAnnotation) 66 | export(Note) 67 | export(NumberValidator) 68 | export(Organization) 69 | export(Paragraph) 70 | export(Parameter) 71 | export(Periodical) 72 | export(Person) 73 | export(PostalAddress) 74 | export(Product) 75 | export(PropertyValue) 76 | export(PublicationIssue) 77 | export(PublicationVolume) 78 | export(Quote) 79 | export(QuoteBlock) 80 | export(Review) 81 | export(SoftwareApplication) 82 | export(SoftwareEnvironment) 83 | export(SoftwareSession) 84 | export(SoftwareSourceCode) 85 | export(StringValidator) 86 | export(Strong) 87 | export(Subscript) 88 | export(Superscript) 89 | export(Table) 90 | export(TableCell) 91 | export(TableRow) 92 | export(ThematicBreak) 93 | export(Thing) 94 | export(ThingTypes) 95 | export(TupleValidator) 96 | export(Union) 97 | export(Validator) 98 | export(ValidatorTypes) 99 | export(Variable) 100 | export(VideoObject) 101 | export(VolumeMount) 102 | -------------------------------------------------------------------------------- /r/_pkgdown.yml: -------------------------------------------------------------------------------- 1 | template: 2 | params: 3 | bootswatch: cosmo 4 | 5 | navbar: 6 | title: R bindings for the Stencila Schema 7 | left: 8 | - text: Home 9 | href: index.html 10 | - text: Reference 11 | href: reference/index.html 12 | right: 13 | - icon: fa-github 14 | href: https://github.com/stencila/schema 15 | -------------------------------------------------------------------------------- /r/inst/WORDLIST: -------------------------------------------------------------------------------- 1 | Bitrate 2 | CodeBlock 3 | CodeChunk 4 | CodeFragment 5 | Codecov 6 | ContactPoint 7 | CreativeWork 8 | CreativeWorks 9 | Datatable 10 | Datatables 11 | DefinedTerm 12 | DefinedTermSet 13 | Emphasised 14 | Filesystem 15 | GiB 16 | Github 17 | ISSN 18 | Math 19 | MSCSW 20 | Mbit 21 | Mbps 22 | MediaObject 23 | NGO 24 | NumberValidator 25 | RStudio 26 | SoftwareSourceCode 27 | Stencila 28 | Subscripted 29 | Superscripted 30 | SyntaxError 31 | ZeroDivisionError 32 | artefacts 33 | asciimath 34 | emphasised 35 | etc 36 | http 37 | https 38 | iana 39 | ie 40 | labelled 41 | labeling 42 | math 43 | mathml 44 | org 45 | pageEnd 46 | pageStart 47 | parentOrganization 48 | programmatically 49 | schemas 50 | stenci 51 | tex 52 | un 53 | undead 54 | validator 55 | validators 56 | variadic 57 | www 58 | xhtml 59 | -------------------------------------------------------------------------------- /r/r.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /r/tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(stencilaschema) 3 | 4 | test_check("stencilaschema") 5 | -------------------------------------------------------------------------------- /r/tests/testthat/helpers.R: -------------------------------------------------------------------------------- 1 | # This file is loaded before any tests are run 2 | 3 | # Turn warnings into errors 4 | options(warn = 2) 5 | -------------------------------------------------------------------------------- /r/tests/testthat/test-types.R: -------------------------------------------------------------------------------- 1 | context("types") 2 | 3 | test_that("core typing functions work", { 4 | expect_equal(last_class(Entity()), "Entity") 5 | expect_true(inherits(Entity(), "Entity")) 6 | }) 7 | 8 | test_that("can construct a simple node", { 9 | jane <- Person( 10 | honorificPrefix = "Dr", 11 | givenNames = c("Jane"), 12 | familyNames = list("Jones", "Jamieson") 13 | ) 14 | expect_equal(jane$familyNames, c("Jones", "Jamieson")) 15 | }) 16 | 17 | test_that("arguments to constructor functions are checked", { 18 | expect_error( 19 | Datatable(), 20 | "Datatable\\$columns is required" 21 | ) 22 | 23 | expect_error( 24 | Datatable( 25 | columns = list( 26 | Person() 27 | ) 28 | ), 29 | "Datatable\\$columns is type list, expected type Array\\(DatatableColumn\\)" 30 | ) 31 | 32 | expect_error( 33 | Datatable( 34 | columns = list( 35 | DatatableColumn( 36 | name = "A" 37 | ) 38 | ) 39 | ), 40 | "DatatableColumn\\$values is required" 41 | ) 42 | 43 | expect_error( 44 | Datatable( 45 | columns = list( 46 | DatatableColumn( 47 | name = "A", 48 | values = matrix() 49 | ) 50 | ) 51 | ), 52 | "DatatableColumn\\$values is type matrix, expected type Array" 53 | ) 54 | 55 | expect_error( 56 | Datatable( 57 | columns = list( 58 | DatatableColumn( 59 | name = "A", 60 | values = 1, 61 | validator = NumberValidator() 62 | ) 63 | ) 64 | ), 65 | "DatatableColumn\\$validator is type NumberValidator, expected type ArrayValidator$" 66 | ) 67 | 68 | expect_equal( 69 | Datatable( 70 | columns = list( 71 | DatatableColumn( 72 | name = "A", 73 | values = 1:10, 74 | validator = ArrayValidator(items = NumberValidator()) 75 | ) 76 | ) 77 | )$columns[[1]]$values, 78 | 1:10 79 | ) 80 | }) 81 | 82 | test_that("primitives in Array properties are treated as scalars", { 83 | chunk <- CodeChunk( 84 | # These should all be scalars 85 | programmingLanguage = "r", 86 | text = "plot(1)", 87 | label = "Figure 1", 88 | id = "fig1", 89 | caption = list( 90 | Heading( 91 | # So should the strings here inside an array... 92 | content = list("Figure title"), 93 | depth = 2 94 | ), 95 | Paragraph( 96 | content = list( 97 | "A paragraph with some", 98 | # Including here, inside a nested array... 99 | Strong(content = list("strong emphasis")), 100 | "in it." 101 | ) 102 | ) 103 | ) 104 | ) 105 | expect_true(inherits(chunk$programmingLanguage, "scalar")) 106 | expect_true(inherits(chunk$text, "scalar")) 107 | expect_true(inherits(chunk$label, "scalar")) 108 | expect_true(inherits(chunk$id, "scalar")) 109 | 110 | expect_equal(class(chunk$caption), "list") 111 | expect_equal(class(chunk$caption[[1]]$depth), c("scalar", "numeric")) 112 | expect_equal(class(chunk$caption[[1]]$content[[1]]), c("scalar", "character")) 113 | }) 114 | -------------------------------------------------------------------------------- /rust/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stencila-schema" 3 | version = "1.16.1" 4 | edition = "2018" 5 | description = "Rust bindings for Stencila Schema" 6 | authors = ["Nokome Bentley "] 7 | license = "Apache-2.0" 8 | readme = "README.md" 9 | homepage = "https://schema.stenci.la" 10 | repository = "https://github.com/stencila/schema" 11 | keywords = ["schema", "executable", "documents"] 12 | 13 | [dependencies] 14 | chrono = "0.4.19" 15 | defaults = "0.2.0" 16 | serde = { version = "1.0.132", features = ["derive"] } 17 | serde_json = "1.0.73" 18 | serde_with = "1.11.0" 19 | strum = { version = "0.23.0", features = ["derive"] } 20 | 21 | [dev-dependencies] 22 | maplit = "1.0.2" 23 | pretty_assertions = "0.7.2" 24 | -------------------------------------------------------------------------------- /rust/Makefile: -------------------------------------------------------------------------------- 1 | all: regen format lint test docs 2 | 3 | regen: 4 | npm run build:rust 5 | 6 | format: 7 | cargo fmt 8 | 9 | lint: 10 | cargo clippy 11 | 12 | test: 13 | cargo test 14 | 15 | docs: 16 | cargo doc --no-deps 17 | 18 | clean: 19 | cargo clean 20 | -------------------------------------------------------------------------------- /rust/README.md: -------------------------------------------------------------------------------- 1 | # Stencila Schema for Rust 2 | 3 | [![Build Status](https://dev.azure.com/stencila/stencila/_apis/build/status/stencila.schema?branchName=master)](https://dev.azure.com/stencila/stencila/_build/latest?definitionId=9&branchName=master) 4 | [![Crates.io](https://img.shields.io/crates/v/stencila-schema)](https://crates.io/crates/stencila-schema) 5 | [![Docs](https://img.shields.io/badge/docs-latest-blue.svg)](https://docs.rs/stencila-schema/latest/stencila_schema/) 6 | 7 | This crate provides Rust bindings for the [Stencila Schema](https://schema.stenci.la). It is primarily aimed at Rust developers wanting to programmatically generate or modify documents, particularly executable documents. For example, it is used in the [Stencila Rust library](https://github.com/stencila/stencila/tree/master/rust). 8 | 9 | ## Install 10 | 11 | ```sh 12 | cargo add stencila_schema 13 | ``` 14 | 15 | ## Use 16 | 17 | This package exports a `struct` for each type of document node in the Stencila Schema e.g. `Article`, `Paragraph`, `CodeChunk`. 18 | 19 | Note that all node properties e.g. `familyNames` are made snake case e.g. `family_names` for consistency with Rust conventions. 20 | 21 | ```rust 22 | let article = Article { 23 | title: Some(ArticleTitle::String("The article title".into())), 24 | authors: Some(vec![ArticleAuthors::Person({ 25 | Person { 26 | given_names: Some(vec!["Jane".into()]), 27 | family_names: Some(vec!["Jones".into()]), 28 | ..Default::default() 29 | } 30 | })]), 31 | content: Some(vec![BlockContent::Paragraph(Paragraph { 32 | content: vec![ 33 | InlineContent::String("A paragraph with a ".into()), 34 | InlineContent::CodeExpression(CodeExpression { 35 | programming_language: Some("r".into()), 36 | text: "2^2".into(), 37 | ..Default::default() 38 | }), 39 | ], 40 | ..Default::default() 41 | })]), 42 | ..Default::default() 43 | }; 44 | ``` 45 | 46 | ## Develop 47 | 48 | Get started by cloning this repository and using `cargo` to run the tests, 49 | 50 | ```bash 51 | git clone git@github.com:stencila/schema 52 | cd schema/rust 53 | cargo test 54 | ``` 55 | 56 | Of course, you need to have Rust [installed](https://rustup.rs). If you want to re-generate `src/types.rs`, you'll also need to have Node.js installed (to generate the Rust code from the schema's YAML files). 57 | -------------------------------------------------------------------------------- /rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![recursion_limit = "256"] 2 | 3 | mod prelude; 4 | pub use prelude::Array; 5 | pub use prelude::Boolean; 6 | pub use prelude::Cord; 7 | pub use prelude::Integer; 8 | pub use prelude::Null; 9 | pub use prelude::Number; 10 | pub use prelude::Object; 11 | pub use prelude::Primitive; 12 | 13 | #[rustfmt::skip] 14 | mod types; 15 | pub use types::*; 16 | 17 | #[rustfmt::skip] 18 | mod schemas; 19 | pub use schemas::*; 20 | -------------------------------------------------------------------------------- /rust/src/prelude.rs: -------------------------------------------------------------------------------- 1 | use chrono::{DateTime, Utc}; 2 | pub use defaults::Defaults; 3 | pub use serde::{Deserialize, Serialize}; 4 | pub use serde_json::Value; 5 | pub use serde_with::skip_serializing_none; 6 | pub use std::{ 7 | collections::BTreeMap, 8 | convert::AsRef, 9 | fmt::{self, Display}, 10 | sync::Arc, 11 | }; 12 | pub use strum::AsRefStr; 13 | 14 | /// A null value 15 | /// 16 | /// This is a struct, rather than a unit variant of `Primitive`, so that 17 | /// it can be treated the same way as other variants when dispatching to 18 | /// trait methods. 19 | #[derive(Clone, Debug)] 20 | pub struct Null {} 21 | 22 | impl Display for Null { 23 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 24 | write!(f, "null") 25 | } 26 | } 27 | 28 | impl Serialize for Null { 29 | fn serialize(&self, serializer: S) -> Result 30 | where 31 | S: serde::Serializer, 32 | { 33 | serializer.serialize_none() 34 | } 35 | } 36 | 37 | impl<'de> Deserialize<'de> for Null { 38 | fn deserialize(deserializer: D) -> Result 39 | where 40 | D: serde::Deserializer<'de>, 41 | { 42 | let value = serde_json::Value::deserialize(deserializer)?; 43 | match value.is_null() { 44 | true => Ok(Null {}), 45 | false => Err(serde::de::Error::custom("Expected a null value")), 46 | } 47 | } 48 | } 49 | 50 | /// A boolean value 51 | pub type Boolean = bool; 52 | 53 | /// An integer value 54 | /// 55 | /// Uses `i64` for maximum precision. 56 | pub type Integer = i64; 57 | 58 | /// A floating point value (a.k.a real number) 59 | /// 60 | /// Uses `i64` for maximum precision. 61 | pub type Number = f64; 62 | 63 | /// An array value (a.k.a. vector) 64 | pub type Array = Vec; 65 | 66 | /// An object value (a.k.a map, dictionary) 67 | /// 68 | /// Uses `BTreeMap` to preserve order. 69 | pub type Object = BTreeMap; 70 | 71 | /// The set of primitive (non-Entity) node types 72 | #[derive(Clone, Debug, Serialize, Deserialize)] 73 | #[serde(untagged)] 74 | pub enum Primitive { 75 | Null(Null), 76 | Boolean(Boolean), 77 | Integer(Integer), 78 | Number(Number), 79 | String(String), 80 | Object(Object), 81 | Array(Array), 82 | } 83 | 84 | /// A newtype derived from `String` 85 | /// 86 | /// Defined primarily so that a customized `Patchable` implementation 87 | /// can be defined for strings where it is more appropriate to replace, 88 | /// rather than diff the string. 89 | #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] 90 | pub struct Cord(pub String); 91 | 92 | // Convenience functions for `Date` 93 | 94 | impl From> for crate::Date { 95 | fn from(date_time: DateTime) -> Self { 96 | Self { 97 | value: date_time.to_rfc3339(), 98 | ..Default::default() 99 | } 100 | } 101 | } 102 | 103 | impl crate::Date { 104 | pub fn now() -> Self { 105 | Self { 106 | value: Utc::now().to_rfc3339(), 107 | ..Default::default() 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /schema/Array.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Array 2 | '@id': stencila:Array 3 | category: data 4 | status: stable 5 | description: A value comprised of several other values. 6 | type: array 7 | -------------------------------------------------------------------------------- /schema/ArrayValidator.schema.yaml: -------------------------------------------------------------------------------- 1 | title: ArrayValidator 2 | '@id': stencila:ArrayValidator 3 | extends: Validator 4 | role: validation 5 | status: unstable 6 | category: data 7 | description: A validator specifying constraints on an array node. 8 | properties: 9 | itemsValidator: 10 | '@id': stencila:itemsValidator 11 | description: Another validator node specifying the constraints on all items in the array. 12 | allOf: 13 | - $ref: ValidatorTypes 14 | contains: 15 | '@id': stencila:contains 16 | description: An array node is valid if at least one of its items is valid against the `contains` schema. 17 | allOf: 18 | - $ref: ValidatorTypes 19 | minItems: 20 | '@id': stencila:minItems 21 | description: An array node is valid if its size is greater than, or equal to, this value. 22 | type: integer 23 | minimum: 0 24 | maxItems: 25 | '@id': stencila:maxItems 26 | description: An array node is valid if its size is less than, or equal to, this value. 27 | type: integer 28 | minimum: 0 29 | uniqueItems: 30 | '@id': stencila:uniqueItems 31 | description: A flag to indicate that each value in the array should be unique. 32 | type: boolean 33 | -------------------------------------------------------------------------------- /schema/Article.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Article 2 | '@id': schema:Article 3 | extends: CreativeWork 4 | category: works 5 | role: primary 6 | status: stable 7 | description: An article, including news and scholarly articles. 8 | $comment: | 9 | This is an implementation, and extension, of schema.org [`Article`](https://schema.org/Article). 10 | It extends schema.org `Article` by, adding a `content` property which must be 11 | an array of [`BlockContent`](./BlockContent), as well as the properties added by 12 | [`CreativeWork`](./CreativeWork) which it extends. 13 | 14 | An `Article` is analogous, and structurally similar to, the JATS XML 15 | [`
`](https://jats.nlm.nih.gov/articleauthoring/tag-library/1.2/element/article.html) 16 | element. 17 | properties: 18 | content: 19 | '@id': stencila:content 20 | description: The structured content of this article. 21 | $comment: | 22 | This is an override of `CreativeWork.content` to restrict node to 23 | `BlockContent` node types e.g `Paragraph`. 24 | type: array 25 | items: 26 | $ref: BlockContent 27 | pageStart: 28 | '@id': schema:pageStart 29 | description: The page on which the article starts; for example "135" or "xiii". 30 | anyOf: 31 | - type: integer 32 | - type: string 33 | pageEnd: 34 | '@id': schema:pageEnd 35 | description: The page on which the article ends; for example "138" or "xvi". 36 | anyOf: 37 | - type: integer 38 | - type: string 39 | pagination: 40 | '@id': schema:pagination 41 | description: | 42 | Any description of pages that is not separated into pageStart and pageEnd; 43 | for example, "1-6, 9, 55". 44 | type: string 45 | examples: 46 | - type: Article 47 | title: 'Recherches sur les substances radioactives' 48 | authors: 49 | - type: 'Person' 50 | honorificPrefix: Dr 51 | givenNames: ['Marie', 'Skłodowska'] 52 | familyNames: ['Curie'] 53 | honorificSuffix: PhD 54 | content: 55 | - Le présent travail a pour but d'exposer les recherches que je poursuis depuis 56 | -------------------------------------------------------------------------------- /schema/AudioObject.schema.yaml: -------------------------------------------------------------------------------- 1 | title: AudioObject 2 | '@id': schema:AudioObject 3 | extends: MediaObject 4 | role: secondary 5 | status: stable 6 | category: works 7 | description: An audio file 8 | properties: 9 | caption: 10 | '@id': schema:caption 11 | description: The caption for this audio recording. 12 | type: string 13 | transcript: 14 | '@id': schema:transcript 15 | description: The transcript of this audio recording. 16 | type: string 17 | examples: 18 | - type: AudioObject 19 | caption: Example Audio File 20 | contentSize: 54321 21 | contentUrl: http://www.example.com/file.mp3 22 | encodingFormat: audio/mpeg3 23 | transcript: This is the transcript for the audio file... 24 | -------------------------------------------------------------------------------- /schema/BlockContent.schema.yaml: -------------------------------------------------------------------------------- 1 | title: BlockContent 2 | category: text 3 | status: stable 4 | description: Union type for valid block content. 5 | anyOf: 6 | - $ref: Claim 7 | - $ref: CodeBlock 8 | - $ref: CodeChunk 9 | - $ref: Collection 10 | - $ref: Figure 11 | - $ref: Heading 12 | - $ref: Include 13 | - $ref: List 14 | - $ref: MathBlock 15 | - $ref: Paragraph 16 | - $ref: QuoteBlock 17 | - $ref: Table 18 | - $ref: ThematicBreak 19 | -------------------------------------------------------------------------------- /schema/Boolean.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Boolean 2 | '@id': schema:Boolean 3 | category: data 4 | status: stable 5 | description: A value that is either true or false 6 | type: boolean 7 | -------------------------------------------------------------------------------- /schema/BooleanValidator.schema.yaml: -------------------------------------------------------------------------------- 1 | title: BooleanValidator 2 | '@id': stencila:BooleanValidator 3 | extends: Validator 4 | category: data 5 | role: validation 6 | status: unstable 7 | description: A schema specifying that a node must be a boolean value. 8 | $comment: | 9 | A node will be valid against this schema if it is either `true` or `false. 10 | Analogous to the JSON Schema `boolean` validation [type](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6.1.1). 11 | properties: {} 12 | -------------------------------------------------------------------------------- /schema/Brand.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Brand 2 | '@id': schema:Brand 3 | extends: Thing 4 | role: tertiary 5 | status: stable 6 | category: other 7 | description: | 8 | A brand used by an organization or person for labeling a product, 9 | product group, or similar. 10 | properties: 11 | logo: 12 | '@id': schema:logo 13 | description: A logo associated with the brand. 14 | anyOf: 15 | - $ref: ImageObject 16 | - type: string 17 | format: uri 18 | reviews: 19 | '@id': schema:review 20 | description: Reviews of the brand. 21 | type: array 22 | items: 23 | type: string 24 | required: 25 | - name 26 | examples: 27 | - type: Brand 28 | name: XYZ 29 | logo: 30 | type: ImageObject 31 | url: https://example.com/xyz.png 32 | caption: Logo of Brand YXZ 33 | reviews: 34 | - Rather average product 35 | - Not sure if would use again 36 | -------------------------------------------------------------------------------- /schema/CiteGroup.schema.yaml: -------------------------------------------------------------------------------- 1 | title: CiteGroup 2 | '@id': stencila:CiteGroup 3 | extends: Entity 4 | category: text 5 | role: secondary 6 | status: unstable 7 | description: A group of Cite nodes. 8 | $comment: | 9 | This type allows you to group associated citations together. 10 | When some content in a [`Creative Work`](./CreativeWork) cites more than one 11 | reference for a particular piece of text, use a `CiteGroup` to encapsulate 12 | multiple [`Cite`](./Cite) nodes. 13 | 14 | At present we do not give a `citationMode` property to a `CiteGroup` since 15 | they will almost always be parenthetical as opposed to narrative. 16 | In other words, it usually only makes sense for individual `Cite` nodes to be 17 | narrative (although they may be connected together within `content` using words 18 | such as "and"). 19 | properties: 20 | items: 21 | '@id': schema:itemListElement 22 | type: array 23 | description: One or more `Cite`s to be referenced in the same surrounding text. 24 | items: 25 | $ref: Cite 26 | required: 27 | - items 28 | examples: 29 | - type: Article 30 | title: An example of using the CiteGroup node type 31 | authors: 32 | - type: Person 33 | givenNames: 34 | - Joe 35 | familyNames: 36 | - Bloggs 37 | content: 38 | - type: Paragraph 39 | content: 40 | - 'Citing two articles ' 41 | - type: CiteGroup 42 | items: 43 | - type: Cite 44 | target: some-one-else-1991 45 | - type: Cite 46 | target: updated-works-2009 47 | - . 48 | references: 49 | - type: Article 50 | id: some-one-else-1991 51 | title: Another article by someone else 52 | authors: 53 | - type: Person 54 | givenNames: 55 | - Some 56 | - One 57 | familyNames: 58 | - Else 59 | datePublished: '1991' 60 | - type: Article 61 | id: update-works-2009 62 | title: A Better Updated Work 63 | authors: 64 | - type: Person 65 | givenNames: 66 | - Some 67 | - Better 68 | familyNames: 69 | - Person 70 | datePublished: '2009' 71 | -------------------------------------------------------------------------------- /schema/Claim.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Claim 2 | '@id': schema:Claim 3 | extends: CreativeWork 4 | category: works 5 | role: secondary 6 | status: unstable 7 | description: A claim represents specific reviewable facts or statements. 8 | $comment: | 9 | It is usually displayed as a block element and can have a label and title. 10 | In the context of a scholarly article this could be a theorem or proof. 11 | See also 12 | - [Schema.org `Claim`](https://schema.org/Claim) 13 | - [JATS ``](https://jats.nlm.nih.gov/publishing/tag-library/1.2/element/statement.html) 14 | properties: 15 | claimType: 16 | '@id': stencila:claimType 17 | description: Kind of the claim. 18 | type: string 19 | enum: 20 | - Statement 21 | - Theorem 22 | - Lemma 23 | - Proof 24 | - Postulate 25 | - Hypothesis 26 | - Proposition 27 | - Corollary 28 | content: 29 | '@id': stencila:content 30 | description: Content of the claim, usually a single paragraph. 31 | type: array 32 | items: 33 | $ref: BlockContent 34 | $comment: | 35 | Most claims will have a single paragraph but could have multiple 36 | paragraphs, tables and even figures. 37 | label: 38 | '@id': stencila:label 39 | description: A short label for the claim. 40 | type: string 41 | required: 42 | - content 43 | -------------------------------------------------------------------------------- /schema/Code.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Code 2 | '@id': stencila:Code 3 | extends: Entity 4 | role: base 5 | status: stable 6 | category: code 7 | description: Base type for non-executable (e.g. `CodeBlock`) and executable (e.g. `CodeExpression`) code nodes. 8 | $comment: | 9 | The most important, and only required, property of a `Code` node is `text`, a `string` of the source code. 10 | There are no restrictions on the length or content of `text` and it is possible for it to be syntactically 11 | invalid for the specified `programmingLanguage`. 12 | properties: 13 | text: 14 | '@id': schema:text 15 | description: The text of the code. 16 | type: string 17 | programmingLanguage: 18 | '@id': schema:programmingLanguage 19 | description: The programming language of the code. 20 | type: string 21 | mediaType: 22 | '@id': schema:encodingFormat 23 | aliases: 24 | - encodingFormat 25 | description: Media type, typically expressed using a MIME format, of the code. 26 | $comment: | 27 | This property allows the differentiation of formats using the same programming language 28 | or variants of a programming language. An example is using `programmingLanguage` "json" and 29 | `encodingFormat` "application/ld+json" for JSON-LD code examples. 30 | type: string 31 | required: 32 | - text 33 | -------------------------------------------------------------------------------- /schema/CodeBlock.schema.yaml: -------------------------------------------------------------------------------- 1 | title: CodeBlock 2 | '@id': stencila:CodeBlock 3 | extends: Code 4 | role: secondary 5 | status: stable 6 | category: code 7 | description: A code block. 8 | properties: {} 9 | -------------------------------------------------------------------------------- /schema/CodeChunk.schema.yaml: -------------------------------------------------------------------------------- 1 | title: CodeChunk 2 | '@id': stencila:CodeChunk 3 | extends: CodeExecutable 4 | category: code 5 | role: secondary 6 | status: unstable 7 | description: A executable chunk of code. 8 | properties: 9 | label: 10 | '@id': stencila:label 11 | description: A short label for the CodeChunk. 12 | type: string 13 | caption: 14 | '@id': schema:caption 15 | description: A caption for the CodeChunk. 16 | $comment: | 17 | An array of nodes or, to be compatible with https://schema.org/caption, a string. 18 | anyOf: 19 | - type: array 20 | items: 21 | $ref: BlockContent 22 | - type: string 23 | executeAuto: 24 | '@id': stencila:executeAuto 25 | description: Under which circumstances the node should be automatically executed. 26 | enum: 27 | - Never 28 | - Needed 29 | - Always 30 | default: Needed 31 | $comment: | 32 | `Never`: Never automatically execute the code chunk. Only execute when the user explicitly runs 33 | the code (or its containing document). 34 | `Needed`: Automatically execute the code chunk if needed. Execute the code chunk if it is an 35 | upstream dependency of a node that has been executed, or is a downstream dependent of a node that 36 | has been executed. 37 | `Always`: Always execute the code, even if it, or its dependencies, are unchanged since the 38 | last time it was executed. 39 | executePure: 40 | '@id': stencila:executePure 41 | description: Whether the code should be treated as side-effect free when executed. 42 | type: boolean 43 | outputs: 44 | '@id': stencila:outputs 45 | description: Outputs from executing the chunk. 46 | type: array 47 | items: 48 | $ref: Node 49 | examples: 50 | - type: CodeChunk 51 | programmingLanguage: python 52 | text: print('Hello world!') 53 | -------------------------------------------------------------------------------- /schema/CodeError.schema.yaml: -------------------------------------------------------------------------------- 1 | title: CodeError 2 | '@id': stencila:CodeError 3 | extends: Entity 4 | role: tertiary 5 | status: unstable 6 | category: code 7 | description: An error that occurred when parsing, compiling or executing a Code node. 8 | properties: 9 | errorType: 10 | '@id': stencila:errorType 11 | description: The type of error e.g. "SyntaxError", "ZeroDivisionError". 12 | $comment: | 13 | Many languages have the concept of alternative types of errors. 14 | For example, Python has various [classes of exceptions](https://docs.python.org/3/tutorial/errors.html). 15 | This property is intended to be used for storing these type names as additional 16 | information that maybe useful to the user attempting to resolve the error. 17 | type: string 18 | errorMessage: 19 | '@id': stencila:errorMessage 20 | aliases: 21 | - message 22 | description: The error message or brief description of the error. 23 | type: string 24 | stackTrace: 25 | '@id': stencila:stackTrace 26 | aliases: 27 | - trace 28 | description: Stack trace leading up to the error. 29 | type: string 30 | required: 31 | - errorMessage 32 | -------------------------------------------------------------------------------- /schema/CodeExpression.schema.yaml: -------------------------------------------------------------------------------- 1 | title: CodeExpression 2 | '@id': stencila:CodeExpression 3 | extends: CodeExecutable 4 | role: secondary 5 | status: unstable 6 | category: code 7 | description: An executable programming code expression. 8 | properties: 9 | output: 10 | '@id': stencila:output 11 | description: The value of the expression when it was last evaluated. 12 | allOf: 13 | - $ref: Node 14 | $comment: 15 | Note that `CodeExpression` nodes lack the `executeAuto` and `executePure` properties that 16 | `CodeChunk` nodes have because they will always be executed (when dependencies) change and 17 | should be side-effect free. 18 | -------------------------------------------------------------------------------- /schema/CodeFragment.schema.yaml: -------------------------------------------------------------------------------- 1 | title: CodeFragment 2 | '@id': stencila:CodeFragment 3 | extends: Code 4 | role: secondary 5 | status: stable 6 | category: code 7 | description: Inline code. 8 | properties: {} 9 | -------------------------------------------------------------------------------- /schema/Collection.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Collection 2 | '@id': schema:Collection 3 | extends: CreativeWork 4 | category: works 5 | role: secondary 6 | status: stable 7 | description: A collection of CreativeWorks or other artifacts. 8 | $comment: | 9 | This is an implementation of schema.org [`Collection`](https://schema.org/Collection). 10 | The `Collection` type allows you to represent a collection of various `CreativeWork` 11 | node types, such as [`Article`](./Article), [`Datatable`](./Datatable) or [`Table`](./Table). 12 | 13 | The schema.org `Collection` has a `collectionSize` property but has not been added here 14 | because it is somewhat redundant e.g. a developer could use `collection.parts.length` instead. 15 | properties: {} 16 | required: 17 | # Note that `parts` is defined in `CreativeWork` but made 18 | # a requirement here. A creative work need not be required to have 19 | # parts, but a collection should. 20 | - parts 21 | -------------------------------------------------------------------------------- /schema/Comment.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Comment 2 | '@id': schema:Comment 3 | extends: CreativeWork 4 | category: works 5 | role: secondary 6 | status: stable 7 | description: A comment on an item, e.g on a Article, or SoftwareSourceCode. 8 | $comment: | 9 | Use the `about` property to define the item that a comment is on and 10 | `commentAspect` to point to a specific part of aspect of that item. 11 | The `content` property should be used for the structured content of the 12 | comment, in preference to the schema.org `text` property (which is expected to 13 | be plain text). Replies to a comment can be added to its `comments` property 14 | or have their `parentItem` set to the parent comment. 15 | properties: 16 | parentItem: 17 | '@id': schema:parentItem 18 | description: The parent comment of this comment. 19 | $ref: Comment 20 | commentAspect: 21 | '@id': stencila:commentAspect 22 | description: The part or facet of the item that is being commented on. 23 | $comment: | 24 | This propery is analagous to the `reviewAspect` property of the `reviewAspect` 25 | type. It is a string to allow flexibility in how the aspect is expressed 26 | depending on the item e.g "technique", for a comment on a painting, or 27 | "some_code.py#L10-L20" for a comment on a software code repository. 28 | type: string 29 | -------------------------------------------------------------------------------- /schema/ConstantValidator.schema.yaml: -------------------------------------------------------------------------------- 1 | title: ConstantValidator 2 | '@id': stencila:ConstantValidator 3 | extends: Validator 4 | role: validation 5 | status: unstable 6 | category: data 7 | description: A validator specifying a constant value that a node must have. 8 | $comment: | 9 | A node will be valid against this validator if it is equal to the 10 | `value` property. Analogous to the JSON Schema [`const` keyword](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6.1.3). 11 | properties: 12 | value: 13 | '@id': schema:value 14 | description: The value that the node must have. 15 | allOf: 16 | - $ref: Node 17 | -------------------------------------------------------------------------------- /schema/ContactPoint.schema.yaml: -------------------------------------------------------------------------------- 1 | title: ContactPoint 2 | '@id': schema:ContactPoint 3 | extends: Thing 4 | role: tertiary 5 | status: stable 6 | category: other 7 | description: A contact point, usually within an organization. 8 | $comment: 9 | This is an implementation of schema.org [`ContactPoint`](https://schema.org/ContactPoint). 10 | It extends schema.org `ContactPoint` by, adding a `content` property which must be 11 | an array of [`BlockContent`](./BlockContent), as well as the properties added by 12 | [`CreativeWork`](./CreativeWork) which it extends. 13 | 14 | `ContactPoint` is analogous, and structurally similar to, the JATS XML 15 | [``](https://jats.nlm.nih.gov/archiving/tag-library/1.1/element/corresp.html) element 16 | and the HTML5 [`
`](https://dev.w3.org/html5/html-author/#the-address-element) element. 17 | properties: 18 | availableLanguages: 19 | '@id': schema:availableLanguage 20 | description: | 21 | Languages (human not programming) in which it is possible to communicate 22 | with the organization/department etc. 23 | type: array 24 | items: 25 | type: string 26 | emails: 27 | '@id': schema:email 28 | description: Email address for correspondence. 29 | type: array 30 | items: 31 | type: string 32 | format: email 33 | telephoneNumbers: 34 | '@id': schema:telephone 35 | aliases: 36 | - telephone 37 | description: Telephone numbers for the contact point. 38 | type: array 39 | items: 40 | type: string 41 | examples: 42 | - type: ContactPoint 43 | availableLanguages: 44 | - English 45 | - Māori 46 | emails: 47 | - welcome@example.org 48 | telephone: '00641234567' 49 | -------------------------------------------------------------------------------- /schema/Datatable.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Datatable 2 | '@id': stencila:Datatable 3 | extends: CreativeWork 4 | category: works 5 | role: primary 6 | status: unstable 7 | description: A table of data. 8 | properties: 9 | columns: 10 | '@id': stencila:columns 11 | description: The columns of data. 12 | type: array 13 | items: 14 | $ref: DatatableColumn 15 | required: 16 | - columns 17 | -------------------------------------------------------------------------------- /schema/DatatableColumn.schema.yaml: -------------------------------------------------------------------------------- 1 | title: DatatableColumn 2 | '@id': stencila:DatatableColumn 3 | extends: Thing 4 | role: secondary 5 | status: unstable 6 | category: data 7 | description: A column of data within a Datatable. 8 | properties: 9 | validator: 10 | '@id': stencila:validator 11 | description: The validator to use to validate data in the column. 12 | allOf: 13 | - $ref: ArrayValidator 14 | values: 15 | '@id': stencila:values 16 | description: The data values of the column. 17 | type: array 18 | items: 19 | $ref: Node 20 | required: 21 | - name 22 | - values 23 | -------------------------------------------------------------------------------- /schema/Date.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Date 2 | '@id': schema:Date 3 | extends: Entity 4 | role: tertiary 5 | status: stable 6 | category: data 7 | description: A date encoded as a ISO 8601 string. 8 | $comment: | 9 | This type serves mainly to disambiguate an ISO 8601 date string from 10 | a plain string. It should generally be used instead of a date formatted string. 11 | parser: date 12 | properties: 13 | value: 14 | '@id': 'schema:value' 15 | description: The date as an ISO 8601 string. 16 | anyOf: 17 | - type: string 18 | format: date-time 19 | - type: string 20 | format: date 21 | - type: string 22 | pattern: \d{4} 23 | required: 24 | - value 25 | -------------------------------------------------------------------------------- /schema/DefinedTerm.schema.yaml: -------------------------------------------------------------------------------- 1 | title: DefinedTerm 2 | '@id': schema:DefinedTerm 3 | extends: Thing 4 | status: stable 5 | role: secondary 6 | category: other 7 | description: A word, name, acronym, phrase, etc. with a formal definition. 8 | $comment: | 9 | Often used in the context of category or subject classification, glossaries or dictionaries, product or creative work types, etc. 10 | Use the `name` property for the term being defined, use `termCode`. If the term has an alpha-numeric code allocated, use 11 | description to provide the definition of the term. 12 | properties: 13 | termCode: 14 | '@id': schema:termCode 15 | description: A code that identifies this DefinedTerm within a DefinedTermSet 16 | type: string 17 | required: 18 | - name 19 | -------------------------------------------------------------------------------- /schema/Delete.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Delete 2 | '@id': stencila:Delete 3 | extends: Mark 4 | role: secondary 5 | status: stable 6 | category: text 7 | description: Content that is marked for deletion 8 | $comment: | 9 | Analogues of `Delete` in other schema include: 10 | - HTML [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del) 11 | - JATS XML [``](https://jats.nlm.nih.gov/archiving/tag-library/1.2/element/strike.html) 12 | - MDAST [`Delete`](https://github.com/syntax-tree/mdast#delete) 13 | - Pandoc [`Strikeout`](https://github.com/jgm/pandoc-types/blob/1.17.5.4/Text/Pandoc/Definition.hs#L258) 14 | properties: {} 15 | examples: 16 | - type: Paragraph 17 | content: 18 | - 'The following is ' 19 | - type: Delete 20 | content: 21 | - marked for deletion 22 | - . 23 | -------------------------------------------------------------------------------- /schema/Emphasis.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Emphasis 2 | '@id': stencila:Emphasis 3 | extends: Mark 4 | role: secondary 5 | status: stable 6 | category: text 7 | description: Emphasised content. 8 | $comment: | 9 | Analogues of `Delete` in other schema include: 10 | - HTML [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em) 11 | - JATS XML [``](https://jats.nlm.nih.gov/archiving/tag-library/1.1/element/italic.html) 12 | - MDAST [`Emphasis`](https://github.com/syntax-tree/mdast#emphasis) 13 | - Pandoc [`Emph`](https://github.com/jgm/pandoc-types/blob/1.17.5.4/Text/Pandoc/Definition.hs#L256) 14 | properties: {} 15 | examples: 16 | - type: Paragraph 17 | content: 18 | - 'The following content has extra ' 19 | - type: Emphasis 20 | content: 21 | - emphasis 22 | -------------------------------------------------------------------------------- /schema/Entity.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Entity 2 | '@id': stencila:Entity 3 | status: stable 4 | role: base 5 | category: other 6 | description: The most simple compound (ie. non-atomic like `number`, `string` etc) type. 7 | $comment: | 8 | This type exists mainly to have a more simple base class than schema.org's `Thing`. 9 | This schema includes special properties that are analogous to JSON-LDs `@type` and `@id`, 10 | as well as a `meta` property that can be used by applications for ad-hoc extensions. 11 | properties: 12 | type: 13 | # This is a special property analogous to JSON-LD's `@type` keyword. 14 | # It is extended with the titles of all descendant types during 15 | # the generation of schema.json files. 16 | '@id': schema:type 17 | description: The name of the type. 18 | type: string 19 | enum: [Entity] 20 | default: Entity 21 | id: 22 | # This is a special property analogous to JSON-LD's `@id` keyword. 23 | '@id': schema:id 24 | description: The identifier for this item. 25 | type: string 26 | meta: 27 | # This property has been added to allow for tools that 28 | # use this schema to add experimental, ad-hoc properties to 29 | # entities. 30 | # Ad-hoc properties that become commonly used may become part of 31 | # the schema proper. 32 | '@id': stencila:meta 33 | description: Metadata associated with this item. 34 | type: object 35 | required: 36 | - type 37 | -------------------------------------------------------------------------------- /schema/EnumValidator.schema.yaml: -------------------------------------------------------------------------------- 1 | title: EnumValidator 2 | '@id': stencila:EnumValidator 3 | extends: Validator 4 | role: validation 5 | status: unstable 6 | category: data 7 | description: A schema specifying that a node must be one of several values. 8 | $comment: Analogous to the JSON Schema [`enum` keyword](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6.1.2). 9 | properties: 10 | values: 11 | '@id': stencila:values 12 | description: A node is valid if it is equal to any of these values. 13 | type: array 14 | items: 15 | $ref: Node 16 | -------------------------------------------------------------------------------- /schema/Enumeration.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Enumeration 2 | '@id': schema:Enumeration 3 | status: stable 4 | role: secondary 5 | category: other 6 | extends: Thing 7 | description: Lists or enumerations, for example, a list of cuisines or music genres, etc. 8 | -------------------------------------------------------------------------------- /schema/Figure.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Figure 2 | '@id': stencila:Figure 3 | extends: CreativeWork 4 | category: works 5 | role: primary 6 | status: unstable 7 | description: Encapsulates one or more images, videos, tables, etc, and provides captions and labels for them. 8 | properties: 9 | caption: 10 | '@id': schema:caption 11 | description: A caption for the figure. 12 | $comment: | 13 | An array of nodes or, to be compatible with https://schema.org/caption, 14 | a string. 15 | anyOf: 16 | - type: array 17 | items: 18 | $ref: BlockContent 19 | - type: string 20 | label: 21 | '@id': stencila:label 22 | description: A short label for the figure. 23 | type: string 24 | -------------------------------------------------------------------------------- /schema/Function.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Function 2 | '@id': stencila:Function 3 | extends: Entity 4 | role: secondary 5 | status: experimental 6 | category: code 7 | description: A function with a name, which might take Parameters and return a value of a certain type. 8 | properties: 9 | name: 10 | '@id': schema:name 11 | description: The name of the function. 12 | type: string 13 | pattern: '[a-z_][A-z0-9_]*' 14 | $comment: | 15 | The name property is not required; this allows for anonymous functions 16 | (although these are not yet implemented in Stencila interpreters). 17 | The regex allows for snake_case and camelCase names but excludes 18 | PascalCase for parameter names. 19 | parameters: 20 | '@id': stencila:parameters 21 | description: The parameters of the function. 22 | type: array 23 | items: 24 | $ref: Parameter 25 | returns: 26 | '@id': stencila:returns 27 | description: The return type of the function. 28 | allOf: 29 | - $ref: ValidatorTypes 30 | -------------------------------------------------------------------------------- /schema/Grant.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Grant 2 | '@id': schema:Grant 3 | extends: Thing 4 | role: tertiary 5 | status: stable 6 | category: other 7 | description: A grant, typically financial or otherwise quantifiable, of resources. 8 | properties: 9 | fundedItems: 10 | '@id': schema:fundedItem 11 | description: Indicates an item funded or sponsored through a Grant. 12 | $comment: | 13 | An array because a grant may have more than one funded item. 14 | type: array 15 | items: 16 | $ref: Thing 17 | sponsors: 18 | '@id': schema:sponsor 19 | description: A person or organization that supports a thing through a pledge, promise, or financial contribution. 20 | $comment: | 21 | An array because a grant may have more than one sponsor. 22 | type: array 23 | items: 24 | anyOf: 25 | - $ref: Person 26 | - $ref: Organization 27 | -------------------------------------------------------------------------------- /schema/Heading.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Heading 2 | '@id': stencila:Heading 3 | extends: Entity 4 | role: secondary 5 | status: stable 6 | category: text 7 | description: A heading. 8 | $comment: | 9 | Analogues of `Delete` in other schema include: 10 | - HTML [`

` to `

`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1) 11 | - JATS XML [``](https://jats.nlm.nih.gov/archiving/tag-library/1.1/element/title.html) 12 | - Pandoc [`Header`](https://github.com/jgm/pandoc-types/blob/1.17.5.4/Text/Pandoc/Definition.hs#L233) 13 | properties: 14 | depth: 15 | '@id': stencila:depth 16 | description: The depth of the heading. 17 | type: integer 18 | default: 1 19 | minimum: 1 20 | maximum: 6 21 | content: 22 | '@id': stencila:content 23 | description: Content of the heading. 24 | type: array 25 | items: 26 | $ref: InlineContent 27 | required: 28 | - content 29 | examples: 30 | - type: Heading 31 | depth: 2 32 | content: 33 | - Secondary Heading 34 | -------------------------------------------------------------------------------- /schema/ImageObject.schema.yaml: -------------------------------------------------------------------------------- 1 | title: ImageObject 2 | '@id': schema:ImageObject 3 | extends: MediaObject 4 | category: works 5 | role: secondary 6 | status: stable 7 | description: An image file. 8 | properties: 9 | caption: 10 | '@id': schema:caption 11 | description: The caption for this image. 12 | type: string 13 | thumbnail: 14 | '@id': schema:thumbnail 15 | description: Thumbnail image of this image. 16 | allOf: 17 | - $ref: ImageObject 18 | examples: 19 | - type: ImageObject 20 | caption: Kiwi 21 | contentSize: '10.4' 22 | contentUrl: http://www.example.com/kiwi.png 23 | encodingFormat: image/png 24 | thumbnail: 25 | type: ImageObject 26 | contentUrl: http://www.example.com/kiwi_mini.png 27 | -------------------------------------------------------------------------------- /schema/Include.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Include 2 | '@id': stencila:Include 3 | category: text 4 | description: Include content from an external source (e.g. file, URL). 5 | role: secondary 6 | status: unstable 7 | extends: Entity 8 | properties: 9 | source: 10 | '@id': stencila:source 11 | description: The external source of the content, a file path or URL. 12 | type: string 13 | mediaType: 14 | '@id': schema:encodingFormat 15 | aliases: 16 | - encodingFormat 17 | description: Media type of the source content. 18 | type: string 19 | $comment: | 20 | Typically expressed using a file name extensions (e.g. `md`) or a 21 | MIME type (e.g. `text/md`). 22 | buildDigest: 23 | '@id': stencila:buildDigest 24 | description: The SHA-256 digest of the `source` and `mediaType` properties the last time the node was built. 25 | type: string 26 | $comment: | 27 | Used to determine whether it is necessary to re-build the node (i.e. update the `content` property 28 | due to new content in the `source` or a change in the `mediaType`). 29 | content: 30 | '@id': stencila:content 31 | description: The structured content decoded from the source. 32 | type: array 33 | items: 34 | $ref: BlockContent 35 | $comment: | 36 | Assumes that included content will be block content i.e. that there will be limited 37 | instances where a user would want to use an `Include` node to transclude inline content. 38 | required: 39 | - source 40 | -------------------------------------------------------------------------------- /schema/InlineContent.schema.yaml: -------------------------------------------------------------------------------- 1 | title: InlineContent 2 | category: text 3 | status: stable 4 | description: Union type for valid inline content. 5 | $comment: | 6 | The order of these types is important because it determines the 7 | order of attempted coercion (this is particularly important for primitive types). 8 | anyOf: 9 | # Entity types in alphabetical order 10 | - $ref: AudioObject 11 | - $ref: Cite 12 | - $ref: CiteGroup 13 | - $ref: CodeExpression 14 | - $ref: CodeFragment 15 | - $ref: Delete 16 | - $ref: Emphasis 17 | - $ref: ImageObject 18 | - $ref: Link 19 | - $ref: MathFragment 20 | - $ref: NontextualAnnotation 21 | - $ref: Note 22 | - $ref: Parameter 23 | - $ref: Quote 24 | - $ref: Strong 25 | - $ref: Subscript 26 | - $ref: Superscript 27 | - $ref: VideoObject 28 | # Primitive types in the order that coercion from 29 | # string should be attempted (for example by Ajv, or by serde_json). 30 | - $ref: 'Null' 31 | - $ref: Boolean 32 | - $ref: Integer 33 | - $ref: Number 34 | - $ref: String 35 | -------------------------------------------------------------------------------- /schema/Integer.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Integer 2 | '@id': schema:Integer 3 | category: data 4 | status: stable 5 | description: A value that is a integer 6 | type: integer 7 | -------------------------------------------------------------------------------- /schema/IntegerValidator.schema.yaml: -------------------------------------------------------------------------------- 1 | title: IntegerValidator 2 | '@id': stencila:IntegerValidator 3 | extends: Validator 4 | role: validation 5 | status: unstable 6 | category: data 7 | description: A validator specifying the constraints on an integer node. 8 | $comment: | 9 | A node will be valid if it is a number with no 10 | fractional part and meets any additional constraints, such as `multipleOf`, 11 | specified in the validator. 12 | Analogous to the JSON Schema `integer` validation [type](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6.1.1). 13 | properties: {} 14 | -------------------------------------------------------------------------------- /schema/Link.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Link 2 | '@id': stencila:Link 3 | extends: Entity 4 | role: secondary 5 | status: unstable 6 | category: text 7 | description: A hyperlink to other pages, sections within the same document, resources, or any URL. 8 | $comment: | 9 | Analogues of `Link` in other schema include: 10 | - HTML [`<a>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a) 11 | - JATS XML [`<ext-link>`](https://jats.nlm.nih.gov/articleauthoring/tag-library/1.2/element/ext-link.html) 12 | - MDAST [`Link`](https://github.com/syntax-tree/mdast#link) 13 | - OpenDocument [`<text:a>`](http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1415212_253892949) 14 | - Pandoc [`Link`](https://github.com/jgm/pandoc-types/blob/1.17.5.4/Text/Pandoc/Definition.hs#L270) 15 | properties: 16 | content: 17 | '@id': stencila:content 18 | description: The textual content of the link. 19 | type: array 20 | items: 21 | $ref: InlineContent 22 | exportFrom: 23 | '@id': stencila:exportFrom 24 | aliases: 25 | - export 26 | description: | 27 | A compilation directive giving the name of the variable to export 28 | to the link target. 29 | type: string 30 | importTo: 31 | '@id': stencila:importTo 32 | aliases: 33 | - import 34 | description: | 35 | A compilation directive giving the name of the variable to import 36 | the link target as. 37 | type: string 38 | target: 39 | '@id': stencila:target 40 | description: The target of the link. 41 | type: string 42 | # See http://json-schema.org/draft-06/json-schema-release-notes.html#formats-uri-vs-uri-reference 43 | # for the difference between `uri` and `uri-reference`. The latter is more permissive, and is 44 | # used here because it allows for intra-doc links using a #fragment only. 45 | format: uri-reference 46 | title: 47 | '@id': schema:headline 48 | description: A title for the link. 49 | $comment: | 50 | This property is analogous to the HTML `title` global attribute which 51 | represents ["advisory information related to the element"](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title) 52 | type: string 53 | relation: 54 | '@id': schema:linkRelationship 55 | description: 56 | The relation between the target and the current thing. 57 | # See https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types 58 | type: string 59 | required: 60 | - content 61 | - target 62 | examples: 63 | - type: Link 64 | content: 65 | - Stencila’s website 66 | target: https://stenci.la 67 | -------------------------------------------------------------------------------- /schema/List.schema.yaml: -------------------------------------------------------------------------------- 1 | title: List 2 | '@id': schema:ItemList 3 | extends: Entity 4 | category: text 5 | role: secondary 6 | status: stable 7 | description: A list of items. 8 | $comment: | 9 | This is an implementation, and renaming, of schema.org [`ItemList`](https://schema.org/ItemList). 10 | Renaming was done as `List` was considered a more developer friendly alternative. Similarly, 11 | schema.org properties `itemListElement` and `itemListOrder` were renamed to `items` and `order`. 12 | Note that, as with every other such renaming in Stencila Schema, a mapping between names is 13 | defined and it is trivial to save Stencila Schema documents using the schema.org vocabulary if so desired. 14 | 15 | Analogues of `List` in other schema include: 16 | - JATS XML [`<list>`](https://jats.nlm.nih.gov/articleauthoring/tag-library/1.2/element/list.html) 17 | - HTML [`<ul>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul) and [`<ol>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol) 18 | - MDAST [`List`](https://github.com/syntax-tree/mdast#list) 19 | - OpenDocument [`<text:list>`](http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1415148_253892949) 20 | properties: 21 | items: 22 | '@id': 'schema:itemListElement' 23 | description: The items in the list 24 | type: array 25 | items: 26 | $ref: ListItem 27 | order: 28 | '@id': 'schema:itemListOrder' 29 | description: Type of ordering. 30 | enum: 31 | - Ascending 32 | - Descending 33 | - Unordered 34 | default: unordered 35 | required: 36 | - items 37 | examples: 38 | - type: List 39 | items: 40 | - type: ListItem 41 | content: 42 | - Item One 43 | - type: ListItem 44 | content: 45 | - Item Two 46 | - type: ListItem 47 | content: 48 | - Item Three 49 | - type: List 50 | items: 51 | - type: ListItem 52 | content: Item One 53 | - type: ListItem 54 | content: 55 | - This is a nested item 56 | - type: List 57 | order: ordered 58 | items: 59 | - type: ListItem 60 | content: 61 | - Nested Item One 62 | - type: ListItem 63 | content: 64 | - Nested Item Two 65 | - type: ListItem 66 | content: 67 | - Nested Item Three 68 | - type: ListItem 69 | content: 70 | - Item Three 71 | - type: List 72 | items: 73 | - type: ListItem 74 | checked: false 75 | content: 76 | - Todo item 77 | - type: ListItem 78 | checked: true 79 | content: 80 | - Completed todo item 81 | -------------------------------------------------------------------------------- /schema/ListItem.schema.yaml: -------------------------------------------------------------------------------- 1 | title: ListItem 2 | '@id': schema:ListItem 3 | extends: Thing 4 | role: tertiary 5 | status: stable 6 | category: text 7 | description: A single item in a list. 8 | $comment: | 9 | This is an implementation, and extension, of schema.org [`ListItem`](https://schema.org/ListItem). 10 | It extends schema.ord `ListItem` by adding `content` and `isChecked` properties. 11 | 12 | Analogues of `ListItem` in other schema include: 13 | - JATS XML `<list-item>`](https://jats.nlm.nih.gov/articleauthoring/tag-library/1.2/element/list-item.html) 14 | - HTML [`<li>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li) 15 | - MDAST [`ListItem`](https://github.com/syntax-tree/mdast#listitem) 16 | - OpenDocument [`<text:list-item>`](http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1415154_253892949) 17 | properties: 18 | content: 19 | '@id': stencila:content 20 | description: The content of the list item. 21 | $comment: Use either `content` or `item`, not both. 22 | anyOf: 23 | - type: array 24 | items: 25 | $ref: BlockContent 26 | - type: array 27 | items: 28 | $ref: InlineContent 29 | isChecked: 30 | '@id': stencila:isChecked 31 | description: A flag to indicate if this list item is checked. 32 | type: boolean 33 | default: false 34 | item: 35 | '@id': schema:item 36 | description: The item represented by this list item. 37 | $comment: Use either `item` or `content`, not both. 38 | allOf: 39 | - $ref: Node 40 | position: 41 | '@id': schema:position 42 | description: The position of the item in a series or sequence of items. 43 | type: integer 44 | examples: 45 | - type: ListItem 46 | content: 47 | - List Item Content 48 | - type: ListItem 49 | content: 50 | - List Item Content 51 | - type: List 52 | order: ordered 53 | items: 54 | - Nested Item One 55 | - type: ListItem 56 | isChecked: true 57 | content: 58 | - Completed todo item 59 | -------------------------------------------------------------------------------- /schema/Mark.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Mark 2 | '@id': stencila:Mark 3 | extends: Entity 4 | role: base 5 | status: stable 6 | category: text 7 | description: | 8 | A base class for nodes that mark some other inline content 9 | in some way (e.g. as being emphasised, or quoted). 10 | properties: 11 | content: 12 | '@id': 'stencila:content' 13 | description: The content that is marked. 14 | type: array 15 | items: 16 | $ref: InlineContent 17 | required: 18 | - content 19 | -------------------------------------------------------------------------------- /schema/Math.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Math 2 | '@id': stencila:Math 3 | extends: Entity 4 | role: base 5 | status: stable 6 | category: math 7 | description: A mathematical variable or equation. 8 | $comment: | 9 | This is a base type for `MathFragment` and `MathBlock` and should not 10 | normally be instantiated. 11 | This type has a similar structure and purpose to `Code` which is a base type 12 | for `CodeFragment`, `CodeBlock` etc. 13 | properties: 14 | errors: 15 | '@id': stencila:errors 16 | description: Errors that occurred when parsing the math equation. 17 | $comment: | 18 | This property is an array of strings. Compare this to `CodeChunk.errors` 19 | which is an array of `CodeError` nodes. Strings are considered to 20 | be sufficient for math parsing errors which usually won't have stack traces, 21 | line numbers etc. 22 | type: array 23 | items: 24 | type: string 25 | mathLanguage: 26 | '@id': stencila:mathLanguage 27 | description: The language used for the equation e.g tex, mathml, asciimath. 28 | type: string 29 | default: 'tex' 30 | text: 31 | '@id': schema:text 32 | description: The text of the equation in the language. 33 | type: string 34 | required: 35 | - text 36 | -------------------------------------------------------------------------------- /schema/MathBlock.schema.yaml: -------------------------------------------------------------------------------- 1 | title: MathBlock 2 | '@id': stencila:MathBlock 3 | extends: Math 4 | role: secondary 5 | status: stable 6 | category: math 7 | description: A block of math, e.g an equation, to be treated as block content. 8 | properties: 9 | label: 10 | '@id': stencila:label 11 | description: A short label for the math block. 12 | type: string 13 | -------------------------------------------------------------------------------- /schema/MathFragment.schema.yaml: -------------------------------------------------------------------------------- 1 | title: MathFragment 2 | '@id': stencila:MathFragment 3 | extends: Math 4 | role: secondary 5 | status: stable 6 | category: math 7 | description: A fragment of math, e.g a variable name, to be treated as inline content. 8 | properties: {} 9 | -------------------------------------------------------------------------------- /schema/MediaObject.schema.yaml: -------------------------------------------------------------------------------- 1 | title: MediaObject 2 | '@id': schema:MediaObject 3 | extends: CreativeWork 4 | category: works 5 | role: base 6 | status: stable 7 | description: | 8 | A media object, such as an image, video, or audio object embedded in a web page or a 9 | downloadable dataset. 10 | properties: 11 | bitrate: 12 | '@id': schema:bitrate 13 | description: | 14 | Bitrate in megabits per second (Mbit/s, Mb/s, Mbps). 15 | type: number 16 | contentSize: 17 | '@id': schema:contentSize 18 | description: | 19 | File size in megabits (Mbit, Mb). 20 | type: number 21 | # See https://github.com/schemaorg/schemaorg/issues/462#issuecomment-98243384 22 | # for why it is useful to have both `contentUrl` and `embedUrl` in addition to `url` 23 | contentUrl: 24 | '@id': schema:contentUrl 25 | description: | 26 | URL for the actual bytes of the media object, for example the image file or video file. 27 | $comment: | 28 | To allow for file paths, including possibly erroneous paths, niether `format` or `pattern` 29 | keywords are used here, or on `embedUrl`. 30 | type: string 31 | embedUrl: 32 | '@id': schema:embedUrl 33 | description: | 34 | URL that can be used to embed the media on a web page via a specific media player. 35 | type: string 36 | mediaType: 37 | '@id': schema:encodingFormat 38 | aliases: 39 | - encodingFormat 40 | description: IANA media type (MIME type). 41 | $comment: | 42 | This property is more restrictive than https://schema.org/encodingFormat which 43 | expects either Text or URL for this property. This schema expects a media type e.g. `text/html` 44 | as listed at http://www.iana.org/assignments/media-types/media-types.xhtml. 45 | type: string 46 | pattern: '^\w+/[-+.\w]+$' 47 | required: 48 | # `contentUrl` is required since it seems to make little sense to have a `MediaObject` 49 | # that does not have it 50 | - contentUrl 51 | examples: 52 | - type: MediaObject 53 | bitrate: '44' 54 | contentSize: '2' 55 | contentUrl: http://www.example.com/file.mp3 56 | encodingFormat: audio/mpeg3 57 | embedUrl: http://www.example.com/full_size/file.mp3 58 | -------------------------------------------------------------------------------- /schema/MonetaryGrant.schema.yaml: -------------------------------------------------------------------------------- 1 | title: MonetaryGrant 2 | '@id': schema:MonetaryGrant 3 | extends: Grant 4 | role: tertiary 5 | status: stable 6 | category: other 7 | description: A monetary grant. 8 | properties: 9 | amounts: 10 | '@id': schema:amount 11 | description: The amount of money. 12 | $comment: | 13 | This property is an array, to allow for multiple amounts, possibly, but not necessarily, 14 | from multiple `funders`. 15 | type: number 16 | funders: 17 | '@id': schema:funder 18 | description: | 19 | A person or organization that supports (sponsors) something through some kind of financial contribution. 20 | $comment: Often a `MonetaryGrant` will have a single funder. 21 | This property is an array to be consistent with `funders` on other types e.g. `CreativeWork`. 22 | type: array 23 | items: 24 | anyOf: 25 | - $ref: Person 26 | - $ref: Organization 27 | -------------------------------------------------------------------------------- /schema/Node.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Node 2 | category: other 3 | status: unstable 4 | description: Union type for all schema nodes, including primitives and entities 5 | $comment: | 6 | The entity types in this union are automatically inserted during the build. 7 | The order of these types is important because it determines the 8 | order of attempted coercion (ie. parsing and reshaping to arrays). 9 | Array should come last to avoid single items (e.g. a single string) 10 | being coerced into an array. 11 | anyOf: 12 | - $ref: 'Null' 13 | - $ref: Boolean 14 | - $ref: Integer 15 | - $ref: Number 16 | - $ref: String 17 | - $ref: Object 18 | - $ref: Array 19 | -------------------------------------------------------------------------------- /schema/NontextualAnnotation.schema.yaml: -------------------------------------------------------------------------------- 1 | title: NontextualAnnotation 2 | '@id': stencila:NontextualAnnotation 3 | extends: Mark 4 | role: secondary 5 | status: stable 6 | category: text 7 | description: Inline text that has a non-textual annotation. 8 | $comment: | 9 | Use cases include annotating spelling errors, denoting proper names in Chinese text, 10 | representing underline text, and other forms of annotation. See 11 | - https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u 12 | - http://html5doctor.com/u-element/ 13 | - https://jats.nlm.nih.gov/archiving/tag-library/1.1/element/underline.html 14 | - https://github.com/jgm/pandoc-types/blob/master/src/Text/Pandoc/Definition.hs#L320 15 | properties: {} 16 | -------------------------------------------------------------------------------- /schema/Note.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Note 2 | '@id': stencila:Note 3 | extends: Entity 4 | category: text 5 | role: secondary 6 | status: unstable 7 | description: Additional content which is not part of the main content of a document. 8 | $comment: | 9 | A note is usually associated with a word or paragraph using a number or other symbol. 10 | It can be displayed as a footnote, endnote, or side note, or in interactive elements. 11 | For analogues, see 12 | - [JATS `<fn>`](https://jats.nlm.nih.gov/publishing/tag-library/1.2/element/fn.html) 13 | - [Pandoc footnotes](https://pandoc.org/MANUAL.html#footnotes) 14 | - [HTML `<aside>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside) 15 | properties: 16 | noteType: 17 | '@id': stencila:noteType 18 | description: Determines where the note content is displayed within the document. 19 | type: string 20 | enum: 21 | - Footnote 22 | - Endnote 23 | - Sidenote 24 | content: 25 | '@id': stencila:content 26 | description: Content of the note, usually a paragraph. 27 | type: array 28 | items: 29 | $ref: BlockContent 30 | $comment: | 31 | Most notes will have a single paragraph but could have multiple 32 | paragraphs, tables and even figures. 33 | required: 34 | - content 35 | -------------------------------------------------------------------------------- /schema/Null.schema.yaml: -------------------------------------------------------------------------------- 1 | title: 'Null' 2 | '@id': stencila:Null 3 | category: data 4 | status: stable 5 | description: The null value 6 | type: 'null' 7 | -------------------------------------------------------------------------------- /schema/Number.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Number 2 | '@id': schema:Number 3 | category: data 4 | status: stable 5 | description: A value that is a number 6 | type: number 7 | -------------------------------------------------------------------------------- /schema/NumberValidator.schema.yaml: -------------------------------------------------------------------------------- 1 | title: NumberValidator 2 | '@id': stencila:NumberValidator 3 | extends: Validator 4 | role: validation 5 | status: unstable 6 | category: data 7 | description: A validator specifying the constraints on a numeric node. 8 | $comment: | 9 | A node will be valid if it is a number that meets the `maximum`, `multipleOf` etc properties. 10 | Analogous to the JSON Schema `number` validation [type](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6.1.1). 11 | Note that the `IntegerValidator` type extends this validator with the additional 12 | constraint that the number have no fractional part. 13 | properties: 14 | minimum: 15 | '@id': stencila:minimum 16 | type: number 17 | description: The inclusive lower limit for a numeric node. 18 | $comment: | 19 | A number is valid if it is greater than, or exactly equal to, `minimum`. 20 | exclusiveMinimum: 21 | '@id': stencila:exclusiveMinimum 22 | type: number 23 | description: The exclusive lower limit for a numeric node. 24 | $comment: | 25 | A number is valid only if it has a value greater than (not equal to) `exclusiveMinimum`. 26 | maximum: 27 | '@id': stencila:maximum 28 | type: number 29 | description: The inclusive upper limit for a numeric node. 30 | $comment: | 31 | A number is valid if it is less than, or exactly equal to, `maximum`. 32 | exclusiveMaximum: 33 | '@id': stencila:exclusiveMaximum 34 | type: number 35 | description: The exclusive upper limit for a numeric node. 36 | $comment: | 37 | A number is valid only if it has a value less than (not equal to) `exclusiveMaximum`. 38 | multipleOf: 39 | '@id': stencila:multipleOf 40 | type: number 41 | exclusiveMinimum: 0 42 | description: A number that a numeric node must be a multiple of. 43 | $comment: | 44 | A number is valid only if division by this value results in an integer. 45 | -------------------------------------------------------------------------------- /schema/Object.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Object 2 | '@id': stencila:Object 3 | category: data 4 | status: stable 5 | description: A value comprised of keyed values. 6 | type: object 7 | -------------------------------------------------------------------------------- /schema/Organization.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Organization 2 | '@id': schema:Organization 3 | extends: Thing 4 | role: secondary 5 | status: stable 6 | category: other 7 | description: An organization such as a school, NGO, corporation, club, etc. 8 | $comment: | 9 | This is an implementation of schema.org [`Organization`](https://schema.org/Organization). 10 | 11 | An `Organization` node is analogous, and structurally similar to: 12 | - Crossref Organization element [`<crossref:organization>`](https://data.crossref.org/reports/help/schema_doc/4.4.0/relations_xsd.html#http___www.crossref.org_relations.xsd_organization) 13 | - JATS XML [`<institution-wrap>`](https://jats.nlm.nih.gov/archiving/tag-library/1.1/element/institution-wrap.html) 14 | - Open Document [`<text:organizations>`](http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1419060_253892949) and [`<text:institutions>`](http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1418948_253892949) 15 | properties: 16 | address: 17 | '@id': schema:address 18 | description: | 19 | Postal address for the organization. 20 | anyOf: 21 | - $ref: PostalAddress 22 | - type: string 23 | brands: 24 | '@id': schema:brand 25 | description: | 26 | Brands that the organization is connected with. 27 | type: array 28 | items: 29 | $ref: Brand 30 | contactPoints: 31 | '@id': schema:contactPoint 32 | description: | 33 | Correspondence/Contact points for the organization. 34 | type: array 35 | items: 36 | $ref: ContactPoint 37 | departments: 38 | '@id': schema:department 39 | description: | 40 | Departments within the organization. For example, Department of Computer Science, Research & Development etc. 41 | type: array 42 | items: 43 | $ref: Organization 44 | funders: 45 | '@id': schema:funder 46 | description: | 47 | Organization(s) or person(s) funding the organization. 48 | type: array 49 | items: 50 | anyOf: 51 | - $ref: Organization 52 | - $ref: Person 53 | legalName: 54 | '@id': schema:legalName 55 | description: | 56 | Legal name for the Organization. Should only include letters and spaces. 57 | type: string 58 | pattern: '[a-zA-Z]' 59 | logo: 60 | '@id': schema:logo 61 | description: The logo of the organization. 62 | $comment: | 63 | This is a singleton property because, at any one time, an organization 64 | will usually only have one logo. 65 | anyOf: 66 | - $ref: ImageObject 67 | - type: string 68 | format: uri 69 | members: 70 | '@id': schema:member 71 | description: | 72 | Person(s) or organization(s) who are members of this organization. 73 | type: array 74 | items: 75 | anyOf: 76 | - $ref: Organization 77 | - $ref: Person 78 | parentOrganization: 79 | '@id': schema:parentOrganization 80 | description: | 81 | Entity that the Organization is a part of. For example, parentOrganization to a department is a university. 82 | allOf: 83 | - $ref: Organization 84 | examples: 85 | - type: Organization 86 | address: Sciences Building, Dunedin, New Zealand 87 | legalName: Department of Natural Sciences 88 | parentOrganization: 89 | type: Organization 90 | legalName: The University of Otago 91 | - type: Organization 92 | address: 362 Leith Street, Dunedin 9054, New Zealand 93 | brands: 94 | - type: Brand 95 | logo: http://www.otago.ac.nz/logo 96 | contactPoints: 97 | - type: ContactPoint 98 | availableLanguages: 99 | - English 100 | - Māori 101 | emails: 102 | - office@otago.ac.nz 103 | telephone: '00641234567' 104 | departments: 105 | - type: Organization 106 | legalName: Commerce 107 | - type: Organization 108 | legalName: Health_Sciences 109 | - type: Organization 110 | legalName: Humanities 111 | funders: 112 | - type: Organization 113 | legalName: MBIE 114 | - type: Organization 115 | legalName: CancerSociety 116 | legalName: The University of Otago 117 | -------------------------------------------------------------------------------- /schema/Paragraph.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Paragraph 2 | '@id': stencila:Paragraph 3 | extends: Entity 4 | role: secondary 5 | status: stable 6 | category: text 7 | description: Paragraph 8 | $comment: | 9 | Analogues of `Paragraph` in other schema include: 10 | - HTML [`<p>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p) 11 | - JATS XML [`<p>`](https://jats.nlm.nih.gov/articleauthoring/tag-library/1.2/element/p.html) 12 | - MDAST [`Paragraph`](https://github.com/syntax-tree/mdast#Paragraph) 13 | - OpenDocument [`<text:p>`](http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1415138_253892949) 14 | - Pandoc [`Para`](https://github.com/jgm/pandoc-types/blob/1.17.5.4/Text/Pandoc/Definition.hs#L220) 15 | properties: 16 | content: 17 | '@id': 'stencila:content' 18 | description: The contents of the paragraph. 19 | type: array 20 | items: 21 | $ref: InlineContent 22 | required: 23 | - content 24 | examples: 25 | - type: Paragraph 26 | content: 27 | - Some text content representing ideas expressed as words. 28 | - type: Paragraph 29 | content: 30 | - Some text with some 31 | - type: Emphasis 32 | content: 33 | - emphasized words 34 | - ' and ' 35 | - type: Strong 36 | content: 37 | - some strongly emphasized words 38 | -------------------------------------------------------------------------------- /schema/Parameter.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Parameter 3 | --- 4 | 5 | ## Structure 6 | 7 | ### Name 8 | 9 | Parameters must have a `name`. This allows them to be referred to by other executable nodes in a document and for callers to specify which parameter of a document or function that they are referring to. So, the simplest parameter would look like this: 10 | 11 | ```json 12 | { 13 | "type": "Parameter", 14 | "name": "weight" 15 | } 16 | ``` 17 | 18 | ### Schema 19 | 20 | You can also specify a `schema` for a parameter which specifies constraints on the values bound to the parameter. 21 | 22 | For example, 23 | 24 | ```json 25 | { 26 | "type": "Parameter", 27 | "name": "weight", 28 | "schema": { 29 | "type": "ArraySchema", 30 | "items": { 31 | "type": "NumberSchema", 32 | "exclusiveMinimum": 0 33 | } 34 | } 35 | } 36 | ``` 37 | 38 | ### Default 39 | 40 | A parameter can have a default value. Of course if you have specified a `schema` for the parameter, then the... 41 | 42 | ## Usage 43 | 44 | Parameters can be used in two places: 45 | 46 | - as an item in the `parameters` property of a `CreativeWork` such as an `Article` or `Function` 47 | 48 | - as a node within the `content` tree of a `CreativeWork` such as an `Article` 49 | 50 | ### Within `parameters` 51 | 52 | Put a parameter in the `parameters` property when you want it to be invisible to the end user of the document. These parameters will not be modifiable by the reader but authors will be able to bind to them when calling a document e.g. 53 | 54 | ```json 55 | { 56 | "type": "Call", 57 | "target": "./my-figure.md", 58 | "arguments": { 59 | ... 60 | } 61 | } 62 | 63 | ``` 64 | 65 | ### Within `content` 66 | 67 | When a parameter is placed in the content of the document it becomes readable, and modifiable by the end user. This allows them to alter the parameter to see how it's value affects other content nodes in the document (e.g. a calculated value, a table, or a plot). 68 | 69 | When defining a parameter within the content of a document it is strongly recommended to specify its `schema`. This provides the user interfaces that are custom to the type of data specified by the schema (e.g. a number keyboard for a parameter with `schema` of type `NumberSchema`). 70 | 71 | ## Encodings 72 | 73 | ### HTML 74 | 75 | > Discuss how different schema types are encoded as different HTML [`<input>` types](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Form_%3Cinput%3E_types) 76 | 77 | ```html 78 | <input id="alpha" type="number" min="0" /> 79 | ``` 80 | -------------------------------------------------------------------------------- /schema/Parameter.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Parameter 2 | '@id': stencila:Parameter 3 | extends: Entity 4 | role: secondary 5 | status: experimental 6 | category: code 7 | description: A parameter of a document or function. 8 | properties: 9 | name: 10 | '@id': schema:name 11 | description: The name of the parameter. 12 | type: string 13 | pattern: '[a-z_][A-z0-9_]*' 14 | $comment: | 15 | This regex allows for snake_case and camelCase names but excludes 16 | PascalCase for names. 17 | value: 18 | '@id': schema:value 19 | description: The current value of the parameter. 20 | allOf: 21 | - $ref: Node 22 | default: 23 | '@id': schema:defaultValue 24 | description: The default value of the parameter. 25 | allOf: 26 | - $ref: Node 27 | validator: 28 | '@id': stencila:validator 29 | description: The validator that the value is validated against. 30 | allOf: 31 | - $ref: ValidatorTypes 32 | executeDigest: 33 | '@id': stencila:executeDigest 34 | description: The SHA-256 digest of the `value` property the last time the node was executed. 35 | type: string 36 | $comment: | 37 | Used to determine whether it is necessary to re-execute the node (i.e to assign a variable 38 | within the document session having `name` and `value`). 39 | isRequired: 40 | '@id': schema:valueRequired 41 | description: Is this parameter required, if not it should have a default or default is assumed to be null. 42 | type: boolean 43 | isVariadic: 44 | '@id': stencila:isVariadic 45 | description: Indicates that this parameter is variadic and can accept multiple arguments. 46 | type: boolean 47 | isExtensible: 48 | '@id': stencila:isExtensible 49 | description: Indicates that this parameter is variadic and can accept multiple named arguments. 50 | type: boolean 51 | required: 52 | - name 53 | -------------------------------------------------------------------------------- /schema/Periodical.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Periodical 2 | '@id': schema:Periodical 3 | extends: CreativeWork 4 | category: works 5 | role: secondary 6 | status: unstable 7 | description: A periodical publication. 8 | $comment: | 9 | A publication in any medium issued in successive parts bearing numerical or chronological designations and intended, 10 | such as a magazine, scholarly journal, or newspaper to continue indefinitely. Often embedded as the `isPartOf` property 11 | in a [`PublicationVolume`](./PublicationVolume). 12 | properties: 13 | dateStart: 14 | '@id': schema:startDate 15 | description: The date this Periodical was first published. 16 | $ref: Date 17 | dateEnd: 18 | '@id': schema:endDate 19 | description: The date this Periodical ceased publication. 20 | $ref: Date 21 | issns: 22 | '@id': schema:issn 23 | description: The International Standard Serial Number(s) (ISSN) that identifies this serial publication. 24 | $comment: | 25 | A periodical may have multiple ISSN (e.g. for online and print versions). 26 | See [issn.org](https://www.issn.org/understanding-the-issn/assignment-rules/the-issn-for-electronic-media/) 27 | for more details. 28 | type: array 29 | items: 30 | type: string 31 | examples: 32 | - type: Periodical 33 | title: Nature 34 | issns: 35 | - 0028-0836 36 | - 1476-4687 37 | dateStart: 1869-11-04 38 | url: https://www.nature.com/ 39 | -------------------------------------------------------------------------------- /schema/Person.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Person 2 | '@id': schema:Person 3 | extends: Thing 4 | role: secondary 5 | status: stable 6 | category: other 7 | description: A person (alive, dead, undead, or fictional). 8 | parser: person 9 | properties: 10 | address: 11 | '@id': schema:address 12 | description: Postal address for the person. 13 | anyOf: 14 | - $ref: PostalAddress 15 | - type: string 16 | affiliations: 17 | '@id': schema:affiliation 18 | description: Organizations that the person is affiliated with. 19 | type: array 20 | items: 21 | $ref: Organization 22 | emails: 23 | '@id': schema:email 24 | description: Email addresses for the person. 25 | type: array 26 | items: 27 | type: string 28 | format: email 29 | familyNames: 30 | '@id': schema:familyName 31 | aliases: 32 | - familyName 33 | - surname 34 | - surnames 35 | - lastName 36 | - lastNames 37 | description: Family name. In the U.S., the last name of a person. 38 | $comment: This can be used along with givenName instead of the name property. 39 | allOf: 40 | - parser: ssi 41 | - type: array 42 | items: 43 | type: string 44 | funders: 45 | '@id': schema:funder 46 | description: | 47 | A person or organization that supports (sponsors) something through 48 | some kind of financial contribution. 49 | type: array 50 | items: 51 | anyOf: 52 | - $ref: Organization 53 | - $ref: Person 54 | givenNames: 55 | '@id': schema:givenName 56 | aliases: 57 | - firstName 58 | - firstNames 59 | # It is necessary to specify this alias because of use of allOf 60 | - givenName 61 | description: Given name. In the U.S., the first name of a person. 62 | $comment: This can be used along with familyName instead of the name property. 63 | allOf: 64 | - parser: ssi 65 | - type: array 66 | items: 67 | type: string 68 | honorificPrefix: 69 | '@id': schema:honorificPrefix 70 | aliases: 71 | - prefix 72 | description: An honorific prefix preceding a person's name such as Dr/Mrs/Mr. 73 | type: string 74 | honorificSuffix: 75 | '@id': schema:honorificSuffix 76 | aliases: 77 | - suffix 78 | description: An honorific suffix after a person's name such as MD/PhD/MSCSW. 79 | type: string 80 | jobTitle: 81 | '@id': schema:jobTitle 82 | description: The job title of the person (for example, Financial Manager). 83 | type: string 84 | memberOf: 85 | '@id': schema:memberOf 86 | description: An organization (or program membership) to which this person belongs. 87 | type: array 88 | items: 89 | $ref: Organization 90 | telephoneNumbers: 91 | '@id': schema:telephone 92 | aliases: 93 | - telephone 94 | description: Telephone numbers for the person. 95 | type: array 96 | items: 97 | type: string 98 | examples: 99 | - type: Person 100 | honorificPrefix: Dr 101 | givenNames: 102 | - Marie 103 | - Skłodowska 104 | familyNames: 105 | - Curie 106 | honorificSuffix: PhD 107 | -------------------------------------------------------------------------------- /schema/PostalAddress.schema.yaml: -------------------------------------------------------------------------------- 1 | title: PostalAddress 2 | '@id': schema:PostalAddress 3 | extends: ContactPoint 4 | role: tertiary 5 | status: stable 6 | category: other 7 | description: A physical mailing address. 8 | properties: 9 | streetAddress: 10 | '@id': schema:streetAddress 11 | description: The street address. 12 | $comment: For example, 10 Downing Street. 13 | type: string 14 | postOfficeBoxNumber: 15 | '@id': schema:postOfficeBoxNumber 16 | description: The post office box number. 17 | type: string 18 | addressLocality: 19 | '@id': schema:addressLocality 20 | description: The locality in which the street address is, and which is in the region. 21 | $comment: For example, London. 22 | type: string 23 | addressRegion: 24 | '@id': schema:addressRegion 25 | description: The region in which the locality is, and which is in the country. 26 | $comment: For example, California or another appropriate first-level Administrative division 27 | type: string 28 | postalCode: 29 | '@id': schema:postalCode 30 | description: The postal code. 31 | $comment: For example, 94043. 32 | type: string 33 | addressCountry: 34 | '@id': schema:addressCountry 35 | description: The country. 36 | $comment: For example, United Kingdom. You can also provide the two-letter ISO 3166-1 alpha-2 country code. 37 | type: string 38 | -------------------------------------------------------------------------------- /schema/Product.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Product 2 | '@id': schema:Product 3 | extends: Thing 4 | role: tertiary 5 | status: stable 6 | category: other 7 | description: | 8 | Any offered product or service. For example, a pair of shoes; 9 | a haircut; or an episode of a TV show streamed online. 10 | $comment: | 11 | The `Product` type allows you to provide details about a product such as the product 12 | brand, logo and ID. This type can be used as any kind of product that is not [`CreativeWork`](./CreativeWork) item. 13 | 14 | `Product` is analogous, and structurally similar to, the 15 | JATS XML [`<product>`](https://jats.nlm.nih.gov/archiving/tag-library/1.1/element/product.html) element which 16 | contains the metadata concerning one product (for example, a book, software package, website, or 17 | hardware component) discussed in an article. 18 | 19 | To meet Google's guidelines for [`Product`](https://developers.google.com/search/docs/data-types/product#product) 20 | instances are required to have `image` and `name` properties. 21 | properties: 22 | brands: 23 | '@id': schema:brand 24 | description: Brands that the product is labelled with. 25 | type: array 26 | items: 27 | $ref: Brand 28 | logo: 29 | '@id': schema:logo 30 | description: The logo of the product. 31 | anyOf: 32 | - $ref: ImageObject 33 | - type: string 34 | format: uri 35 | productID: 36 | '@id': schema:productID 37 | description: Product identification code. 38 | type: string 39 | examples: 40 | - type: Product 41 | brand: 42 | type: Brand 43 | name: Astro 44 | name: Astrolabe 45 | logo: 46 | type: ImageObject 47 | contentUrl: http://www.product-astrolabe.com/logo.png 48 | caption: Astrolabe Logo 49 | productID: AA55 50 | -------------------------------------------------------------------------------- /schema/PropertyValue.schema.yaml: -------------------------------------------------------------------------------- 1 | title: PropertyValue 2 | '@id': schema:PropertyValue 3 | extends: Thing 4 | status: stable 5 | role: secondary 6 | category: other 7 | description: A property-value pair. 8 | $comment: | 9 | Always use specific properties when they exist and you can populate them. 10 | Using `PropertyValue` as a substitute will typically not convey as much semantic 11 | information as using the specific property. 12 | 13 | Most of the time a `PropertyValue` node will need a `value` property 14 | (e.g. most of the examples on https://schema.org/PropertyValue have one) 15 | so this schema make that property required. 16 | 17 | This type is mainly provided for use in `Thing.identifiers` (see the notes there). 18 | properties: 19 | propertyID: 20 | '@id': schema:propertyID 21 | description: A commonly used identifier for the characteristic represented by the property. 22 | type: string 23 | value: 24 | '@id': schema:value 25 | description: The value of the property. 26 | anyOf: 27 | - type: boolean 28 | - type: integer 29 | - type: number 30 | - type: string 31 | $comment: | 32 | This follows the expected types of https://schema.org/value except for `StructuredValue`, 33 | which at the time of writing was not implemented in this schema. 34 | required: 35 | - value 36 | -------------------------------------------------------------------------------- /schema/PublicationIssue.schema.yaml: -------------------------------------------------------------------------------- 1 | title: PublicationIssue 2 | '@id': schema:PublicationIssue 3 | extends: CreativeWork 4 | category: works 5 | role: secondary 6 | status: stable 7 | description: | 8 | A part of a successively published publication such as a periodical or publication 9 | volume, often numbered. 10 | properties: 11 | issueNumber: 12 | '@id': schema:issueNumber 13 | description: Identifies the issue of publication; for example, "iii" or "2". 14 | anyOf: 15 | - type: integer 16 | - type: string 17 | pageStart: 18 | '@id': schema:pageStart 19 | description: The page on which the issue starts; for example "135" or "xiii". 20 | anyOf: 21 | - type: integer 22 | - type: string 23 | pageEnd: 24 | '@id': schema:pageEnd 25 | description: The page on which the issue ends; for example "138" or "xvi". 26 | anyOf: 27 | - type: integer 28 | - type: string 29 | pagination: 30 | '@id': schema:pagination 31 | description: | 32 | Any description of pages that is not separated into pageStart and pageEnd; 33 | for example, "1-6, 9, 55". 34 | type: string 35 | examples: 36 | - type: PublicationIssue 37 | url: https://www.nature.com/nature/volumes/571/issues/7766 38 | issueNumber: 571 39 | datePublished: 2019-07-25 40 | isPartOf: 41 | type: PublicationVolume 42 | volumeNumber: 571 43 | isPartOf: 44 | type: Periodical 45 | title: Nature 46 | -------------------------------------------------------------------------------- /schema/PublicationVolume.schema.yaml: -------------------------------------------------------------------------------- 1 | title: PublicationVolume 2 | '@id': schema:PublicationVolume 3 | extends: CreativeWork 4 | category: works 5 | role: secondary 6 | status: stable 7 | description: | 8 | A part of a successively published publication such as a periodical or multi-volume work. 9 | $comment: | 10 | Often embedded as the `isPartOf` property in a [`PublicationIssue`](./PublicationIssue). 11 | properties: 12 | pageStart: 13 | '@id': schema:pageStart 14 | description: The page on which the volume starts; for example "135" or "xiii". 15 | anyOf: 16 | - type: integer 17 | - type: string 18 | pageEnd: 19 | '@id': schema:pageEnd 20 | description: The page on which the volume ends; for example "138" or "xvi". 21 | anyOf: 22 | - type: integer 23 | - type: string 24 | pagination: 25 | '@id': schema:pagination 26 | description: | 27 | Any description of pages that is not separated into pageStart and pageEnd; 28 | for example, "1-6, 9, 55". 29 | type: string 30 | volumeNumber: 31 | '@id': schema:volumeNumber 32 | description: | 33 | Identifies the volume of publication or multi-part work; for example, "iii" or "2". 34 | anyOf: 35 | - type: integer 36 | - type: string 37 | examples: 38 | - type: PublicationVolume 39 | volumeNumber: 571 40 | isPartOf: 41 | type: Periodical 42 | title: Nature 43 | -------------------------------------------------------------------------------- /schema/Quote.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Quote 2 | '@id': stencila:Quote 3 | extends: Mark 4 | role: secondary 5 | status: stable 6 | category: text 7 | description: Inline, quoted content. 8 | properties: 9 | cite: 10 | '@id': stencila:cite 11 | description: The source of the quote. 12 | anyOf: 13 | - $ref: Cite 14 | - type: string 15 | format: uri 16 | -------------------------------------------------------------------------------- /schema/QuoteBlock.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Quote Block 3 | authors: [] 4 | --- 5 | 6 | include: ../public/QuoteBlock.schema.md 7 | ::: 8 | A section quoted from somewhere else. 9 | 10 | | Entity | type | The name of the type and all descendant types. | string | 11 | | ---------- | -------- | ---------------------------------------------- | ------ | 12 | | Entity | id | The identifier for this item. | string | 13 | | QuoteBlock | citation | The source of the quote | string | 14 | | QuoteBlock | content | | array | 15 | 16 | ::: 17 | 18 | The `QuoteBlock` schema represents an extended quoted sections. 19 | 20 | # Examples 21 | 22 | ## Simple 23 | 24 | ```json 25 | { 26 | "type": "QuoteBlock", 27 | "content": [ 28 | { 29 | "type": "Paragraph", 30 | "content": [ 31 | "If you wish to make an apple pie from scratch, you must first invent the universe.", 32 | "by Carl Sagan - Cosmos" 33 | ] 34 | } 35 | ] 36 | } 37 | ``` 38 | 39 | ## With Attribution URI 40 | 41 | ```json 42 | { 43 | "type": "QuoteBlock", 44 | "content": [ 45 | { 46 | "type": "Paragraph", 47 | "content": [ 48 | "If you wish to make an apple pie from scratch, you must first invent the universe.", 49 | "by Carl Sagan — Cosmos" 50 | ] 51 | } 52 | ], 53 | "citation": "https://www.goodreads.com/quotes/32952-if-you-wish-to-make-an-apple-pie-from-scratch" 54 | } 55 | ``` 56 | 57 | # Encodings 58 | 59 | include: ../docs/type-encodings-intro.md 60 | ::: 61 | This section describes common encodings for this node type. These samples are generated from the above examples by [Encoda](https://stencila.github.io/encoda), but you can also author them in each format. 62 | ::: 63 | 64 | ## HTML 65 | 66 | `QuoteBlock` is analogous to the HTML [`<blockquote>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote) element. 67 | 68 | ### Simple 69 | 70 | ```html 71 | 72 | ``` 73 | 74 | ### With Attribution URI 75 | 76 | ```html 77 | 78 | ``` 79 | 80 | ## JATS 81 | 82 | `Quote` is analogous to the JATS [`<disp-quote>`](https://jats.nlm.nih.gov/articleauthoring/tag-library/1.2/element/disp-quote.html) type, and the [`<attrib>` element](https://jats.nlm.nih.gov/articleauthoring/tag-library/1.2/element/attrib.html) can be used for the `citation` field from the Stencila schema. 83 | 84 | ### Simple 85 | 86 | ```jats 87 | 88 | ``` 89 | 90 | ### With Attribution URI 91 | 92 | ```jats 93 | 94 | ``` 95 | 96 | ## mdast 97 | 98 | `QuoteBlock` is analogous to the mdast [`Blockquote`](https://github.com/syntax-tree/mdast#blockquote) node type. 99 | 100 | ### Simple 101 | 102 | ```markdown 103 | 104 | ``` 105 | 106 | ### With Attribution URI 107 | 108 | ```markdown 109 | 110 | ``` 111 | 112 | ## OpenDocument 113 | 114 | `QuoteBlock` does not have an analogous OpenDocument element. 115 | 116 | ## Pandoc 117 | 118 | `QuoteBlock` is analogous to the Pandoc [`BlockQuote`](https://github.com/jgm/pandoc-types/blob/1.17.5.4/Text/Pandoc/Definition.hs#L224) type. 119 | 120 | ### Simple 121 | 122 | ```pandoc 123 | 124 | ``` 125 | 126 | ### With Attribution URI 127 | 128 | ```pandoc 129 | 130 | ``` 131 | 132 | [//]: # 'WIP: Needs QuoteBlock JSON Fixes' 133 | -------------------------------------------------------------------------------- /schema/QuoteBlock.schema.yaml: -------------------------------------------------------------------------------- 1 | title: QuoteBlock 2 | '@id': stencila:QuoteBlock 3 | extends: Entity 4 | role: secondary 5 | status: stable 6 | category: text 7 | description: | 8 | A section quoted from somewhere else. 9 | properties: 10 | cite: 11 | '@id': stencila:cite 12 | description: The source of the quote. 13 | anyOf: 14 | - $ref: Cite 15 | - type: string 16 | format: uri 17 | content: 18 | '@id': 'stencila:content' 19 | description: The content of the quote. 20 | type: array 21 | items: 22 | $ref: BlockContent 23 | required: 24 | - content 25 | -------------------------------------------------------------------------------- /schema/Review.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Review 2 | '@id': schema:Review 3 | extends: CreativeWork 4 | category: works 5 | role: secondary 6 | status: stable 7 | description: A review of an item, e.g of an Article, or SoftwareSourceCode. 8 | $comment: | 9 | Use the `content` property for the structured content of the review in 10 | preference to the schema.org `text` or `reviewBody` properties (which 11 | have plain text as the expected type). 12 | properties: 13 | itemReviewed: 14 | '@id': schema:itemReviewed 15 | description: The item that is being reviewed. 16 | $ref: Thing 17 | reviewAspect: 18 | '@id': schema:reviewAspect 19 | description: The part or facet of the item that is being reviewed. 20 | type: string 21 | -------------------------------------------------------------------------------- /schema/SoftwareApplication.schema.yaml: -------------------------------------------------------------------------------- 1 | title: SoftwareApplication 2 | '@id': schema:SoftwareApplication 3 | extends: CreativeWork 4 | category: works 5 | role: primary 6 | status: stable 7 | description: | 8 | A software application. 9 | $comment: | 10 | `SoftwareApplication` represents a software application that can be located by name and version. 11 | It may be fetched in binary format or some package manager (npm, pip, etc) could fetch and compile the source code. 12 | Although by using the `softwareRequirements` property it is possible to represent a full hierarchy 13 | of required packages, normally it is adequate to only list the immediate dependencies and allow 14 | the system/language package manager to resolve the rest. 15 | properties: 16 | softwareRequirements: 17 | '@id': schema:softwareRequirements 18 | description: | 19 | Requirements for application, including shared libraries that 20 | are not included in the application distribution. 21 | type: array 22 | items: 23 | $ref: SoftwareApplication 24 | softwareVersion: 25 | '@id': schema:softwareVersion 26 | description: Version of the software. 27 | type: string 28 | -------------------------------------------------------------------------------- /schema/SoftwareEnvironment.schema.yaml: -------------------------------------------------------------------------------- 1 | title: SoftwareEnvironment 2 | '@id': stencila:SoftwareEnvironment 3 | extends: Thing 4 | role: primary 5 | status: experimental 6 | category: code 7 | description: A computational environment. 8 | properties: 9 | extends: 10 | '@id': stencila:extends 11 | description: Other environments that this environment extends by adding or removing packages., 12 | type: array 13 | items: 14 | $ref: SoftwareEnvironment 15 | adds: 16 | '@id': stencila:adds 17 | description: The packages that this environment adds to the base environments listed under `extends` (if any)., 18 | type: array 19 | items: 20 | $ref: SoftwareSourceCode 21 | removes: 22 | '@id': stencila:removes 23 | description: The packages that this environment removes from the base environments listed under `extends` (if any)., 24 | type: array 25 | items: 26 | $ref: SoftwareSourceCode 27 | required: 28 | - name 29 | -------------------------------------------------------------------------------- /schema/SoftwareSession.schema.yaml: -------------------------------------------------------------------------------- 1 | title: SoftwareSession 2 | '@id': stencila:SoftwareSession 3 | extends: Thing 4 | role: primary 5 | status: experimental 6 | category: code 7 | description: | 8 | Definition of a compute session, including its software and compute resource 9 | requirements and status. 10 | $comment: | 11 | Usually used to define the environment that is required to execute an 12 | executable document. 13 | 14 | This is "inspired" by the [OCI Runtime Config Schema](https://github.com/opencontainers/runtime-spec/blob/master/schema/config-schema.json) 15 | There are a number of properties that did not seem relevant to our use as well as some 16 | references that did not seem to be required. We try to stay consistent with the naming 17 | used but have dereferenced and combined the config schema and 18 | [Linux Schema](https://github.com/opencontainers/runtime-spec/blob/master/schema/defs-linux.json) 19 | to use the cpu and memory limits. 20 | properties: 21 | environment: 22 | '@id': stencila:environment 23 | description: The software environment to execute this session in. 24 | allOf: 25 | - $ref: SoftwareEnvironment 26 | dateStart: 27 | '@id': schema:startDate 28 | description: The date-time that the session began. 29 | allOf: 30 | - $ref: Date 31 | dateEnd: 32 | '@id': schema:endDate 33 | description: The date-time that the session ended. 34 | allOf: 35 | - $ref: Date 36 | status: 37 | '@id': stencila:sessionStatus 38 | description: The status of the session (starting, stopped, etc). 39 | enum: 40 | - Unknown 41 | - Starting 42 | - Started 43 | - Stopping 44 | - Stopped 45 | - Failed 46 | clientsRequest: 47 | '@id': stencila:clientsRequest 48 | description: The maximum number of concurrent clients requested for the session. 49 | type: number 50 | minimum: 0 51 | clientsLimit: 52 | '@id': stencila:clientsLimit 53 | description: The maximum number of concurrent clients the session is limited to. 54 | type: number 55 | minimum: 0 56 | durationRequest: 57 | '@id': stencila:durationRequest 58 | description: The maximum duration (seconds) requested for the session. 59 | type: number 60 | minimum: 0 61 | durationLimit: 62 | '@id': stencila:durationLimit 63 | description: The maximum duration (seconds) the session is limited to. 64 | type: number 65 | minimum: 0 66 | timeoutRequest: 67 | '@id': stencila:timeoutRequest 68 | description: The inactivity timeout (seconds) requested for the session. 69 | type: number 70 | minimum: 0 71 | timeoutLimit: 72 | '@id': stencila:timeoutLimit 73 | description: The inactivity timeout (seconds) the session is limited to. 74 | type: number 75 | minimum: 0 76 | cpuRequest: 77 | '@id': stencila:cpuRequest 78 | description: The amount of CPU requested for the session. 79 | type: number 80 | minimum: 0 81 | cpuLimit: 82 | '@id': stencila:cpuLimit 83 | description: The amount of CPU the session is limited to. 84 | type: number 85 | minimum: 0 86 | memoryRequest: 87 | '@id': stencila:memoryRequest 88 | description: The amount of memory requested for the session. 89 | type: number 90 | minimum: 0 91 | memoryLimit: 92 | '@id': stencila:memoryLimit 93 | description: The amount of memory that the session is limited to. 94 | type: number 95 | minimum: 0 96 | networkTransferRequest: 97 | '@id': stencila:networkTransferRequest 98 | description: The amount of network data transfer (GiB) requested for the session. 99 | type: number 100 | minimum: 0 101 | networkTransferLimit: 102 | '@id': stencila:networkTransferLimit 103 | description: The amount of network data transfer (GiB) that the session is limited to. 104 | type: number 105 | minimum: 0 106 | volumeMounts: 107 | '@id': stencila:volumeMounts 108 | description: Volumes to mount in the session. 109 | type: array 110 | items: 111 | $ref: VolumeMount 112 | -------------------------------------------------------------------------------- /schema/SoftwareSourceCode.schema.yaml: -------------------------------------------------------------------------------- 1 | title: SoftwareSourceCode 2 | '@id': schema:SoftwareSourceCode 3 | extends: CreativeWork 4 | category: works 5 | role: primary 6 | status: stable 7 | description: | 8 | Computer programming source code. Example: Full (compile ready) solutions, code snippet samples, scripts, templates. 9 | properties: 10 | codeRepository: 11 | '@id': schema:codeRepository 12 | description: | 13 | Link to the repository where the un-compiled, human readable code and related 14 | code is located. 15 | type: string 16 | format: uri 17 | codeSampleType: 18 | '@id': schema:codeSampleType 19 | description: | 20 | What type of code sample: full (compile ready) solution, code snippet, inline code, scripts, template. 21 | type: string 22 | programmingLanguage: 23 | '@id': schema:programmingLanguage 24 | description: | 25 | The computer programming language. 26 | type: string 27 | runtimePlatform: 28 | '@id': schema:runtimePlatform 29 | description: | 30 | Runtime platform or script interpreter dependencies (Example - Java v1, 31 | Python2.3, .Net Framework 3.0). 32 | type: array 33 | items: 34 | type: string 35 | softwareRequirements: 36 | '@id': schema:softwareRequirements 37 | description: Dependency requirements for the software. 38 | type: array 39 | items: 40 | anyOf: 41 | - $ref: SoftwareSourceCode 42 | - $ref: SoftwareApplication 43 | - type: string 44 | targetProducts: 45 | '@id': schema:targetProduct 46 | description: | 47 | Target operating system or product to which the code applies. 48 | type: array 49 | items: 50 | $ref: SoftwareApplication 51 | -------------------------------------------------------------------------------- /schema/String.schema.yaml: -------------------------------------------------------------------------------- 1 | title: String 2 | '@id': schema:Text 3 | category: data 4 | status: stable 5 | description: A value comprised of a string of characters 6 | type: string 7 | -------------------------------------------------------------------------------- /schema/StringValidator.schema.yaml: -------------------------------------------------------------------------------- 1 | title: StringValidator 2 | '@id': stencila:StringValidator 3 | extends: Validator 4 | role: validation 5 | status: unstable 6 | category: data 7 | description: A schema specifying constraints on a string node. 8 | $comment: | 9 | A node will be valid against the schema if it is a string that 10 | meets the schemas `minLength`, `maxLength` and `pattern` properties. 11 | Analogous to the JSON Schema `string` validation [type](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6.1.1). 12 | properties: 13 | minLength: 14 | '@id': stencila:minLength 15 | type: integer 16 | minimum: 0 17 | description: The minimum length for a string node. 18 | $comment: | 19 | A string is valid if its length is greater than, or exactly equal to, `minLength`. 20 | maxLength: 21 | '@id': stencila:maxLength 22 | type: integer 23 | minimum: 0 24 | description: The maximum length for a string node. 25 | $comment: | 26 | A string is valid if its length is less than, or exactly equal to, `maxLength`. 27 | pattern: 28 | '@id': stencila:pattern 29 | type: string 30 | description: A regular expression that a string node must match. 31 | $comment: | 32 | A string is valid if it is matched by the regular expression. 33 | -------------------------------------------------------------------------------- /schema/Strong.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Strong 3 | authors: [] 4 | --- 5 | 6 | include: ../public/Strong.schema.md 7 | ::: 8 | Strongly emphasised content. Analagous to, - JATS \[\`<bold>\`](https://jats.nlm.nih.gov/archiving/tag-library/1.1/element/bold.html) - HTML \[\`<strong>\`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong) - MDAST \[\`Strong\`](https://github.com/syntax-tree/mdast#strong) - Pandoc \[\`Strong\`](https://github.com/jgm/pandoc-types/blob/1.17.5.4/Text/Pandoc/Definition.hs#L257) 9 | 10 | | Entity | type | The name of the type and all descendant types. | string | 11 | | ------ | ------- | ---------------------------------------------- | ------ | 12 | | Entity | id | The identifier for this item. | string | 13 | | Mark | content | The content that is marked. | | 14 | | array | | | | 15 | 16 | ::: 17 | 18 | The `Strong` schema represents strongly emphasised content. It can contain any valid [`InlineContent`](/schema/InlineContent) nodes. 19 | 20 | # Examples 21 | 22 | ## Simple 23 | 24 | ```json validate import=simple 25 | { 26 | "type": "Strong", 27 | "content": ["Some important information"] 28 | } 29 | ``` 30 | 31 | ## Nested types 32 | 33 | ```json validate import=nested 34 | { 35 | "type": "Strong", 36 | "content": [ 37 | "Some ", 38 | { "type": "Delete", "content": ["important"] }, 39 | "essential information" 40 | ] 41 | } 42 | ``` 43 | 44 | # Encodings 45 | 46 | include: ../docs/type-encodings-intro.md 47 | ::: 48 | This section describes common encodings for this node type. These samples are generated from the above examples by [Encoda](https://stencila.github.io/encoda), but you can also author them in each format. 49 | ::: 50 | 51 | ## JATS 52 | 53 | `Strong` is analogous, and structurally similar to, the JATS [`<bold>`](https://jats.nlm.nih.gov/articleauthoring/tag-library/1.2/element/aut-elem-sec-intro.html) type. 54 | 55 | ### Simple 56 | 57 | ```jats export=simple 58 | <p><bold>Some important information</bold></p> 59 | 60 | ``` 61 | 62 | ### Nested types 63 | 64 | ```jats export=nested 65 | <p><bold>Some <strike>important</strike>essential information</bold></p> 66 | 67 | ``` 68 | 69 | ## mdast 70 | 71 | `Strong` is analogous to the mdast [`Strong`](https://github.com/syntax-tree/mdast#strong) node type. 72 | 73 | ### Simple 74 | 75 | ```markdown export=simple 76 | **Some important information** 77 | ``` 78 | 79 | ### Nested types 80 | 81 | ```markdown export=nested 82 | **Some ~~important~~essential information** 83 | ``` 84 | 85 | ## OpenDocument 86 | 87 | `Strong` is similar to the OpenDocument [`<style:font-adornments>`](http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1417910_253892949) attribute. 88 | 89 | [//]: # 'WIP: Some <strong> elements are ending up in the generated HTML doc making everything bold' 90 | -------------------------------------------------------------------------------- /schema/Strong.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Strong 2 | '@id': stencila:Strong 3 | extends: Mark 4 | role: secondary 5 | status: stable 6 | category: text 7 | description: Strongly emphasised content. 8 | properties: {} 9 | -------------------------------------------------------------------------------- /schema/Subscript.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Subscript 3 | --- 4 | 5 | Analagous to 6 | 7 | - JATS [`<sub>`](https://jats.nlm.nih.gov/archiving/tag-library/1.1/element/sub.html) 8 | - HTML [`<sub>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub) 9 | - Pandoc [`Subscript`](https://github.com/jgm/pandoc-types/blob/1.17.5.4/Text/Pandoc/Definition.hs#L260) 10 | -------------------------------------------------------------------------------- /schema/Subscript.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Subscript 2 | '@id': stencila:Subscript 3 | extends: Mark 4 | role: secondary 5 | status: stable 6 | category: text 7 | description: Subscripted content. 8 | properties: {} 9 | -------------------------------------------------------------------------------- /schema/Superscript.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Superscript 2 | '@id': stencila:Superscript 3 | extends: Mark 4 | role: secondary 5 | status: stable 6 | category: text 7 | description: Superscripted content. 8 | properties: {} 9 | -------------------------------------------------------------------------------- /schema/Table.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Table 2 | '@id': schema:Table 3 | extends: CreativeWork 4 | category: works 5 | role: primary 6 | status: unstable 7 | description: A table. 8 | properties: 9 | caption: 10 | '@id': schema:caption 11 | description: A caption for the table. 12 | $comment: | 13 | An array of nodes or, to be compatible with https://schema.org/caption, 14 | a string. 15 | anyOf: 16 | - type: array 17 | items: 18 | $ref: BlockContent 19 | - type: string 20 | label: 21 | '@id': stencila:label 22 | description: A short label for the table. 23 | type: string 24 | rows: 25 | '@id': stencila:rows 26 | description: | 27 | Rows of cells in the table. 28 | type: array 29 | items: 30 | $ref: TableRow 31 | required: 32 | - rows 33 | -------------------------------------------------------------------------------- /schema/TableCell.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: TableCell 3 | authors: [] 4 | --- 5 | 6 | include: ../public/TableCell.schema.md 7 | ::: 8 | A cell within a \`Table\`. 9 | 10 | | Entity | type | The name of the type and all descendant types. | string | 11 | | --------- | ---- | ------------------------------------------------------------------------------------------- | ------ | 12 | | Entity | id | The identifier for this item. | string | 13 | | TableCell | name | The name of the cell. Cell's have an implicit name derived from their position in the table | | 14 | 15 | e.g. \`C4\` for the cell in the third column and fourth row. However this name can be overridden with an explicit name, e.g. \`rate\`. | string | | TableCell | colspan | How many columns the cell extends. | integer | | TableCell | rowspan | How many columns the cell extends. | integer | | TableCell | content | Contents of the table cell. | array | 16 | ::: 17 | 18 | A `TableCell` type represents a single cell in a [`Table`](/schema/Table). It contains properties defining the contents, and optionally the dimensions of the cell within the table. 19 | 20 | # Examples 21 | 22 | ## Simple 23 | 24 | This is the most basic form of `TableCell` you can have, only requiring the `content` field. 25 | 26 | ```json import=simple 27 | { 28 | "type": "TableCell", 29 | "content": [1] 30 | } 31 | ``` 32 | 33 | ## Table Cell with all properties defined 34 | 35 | ```json import=full 36 | { 37 | "type": "TableCell", 38 | "colspan": 2, 39 | "content": [1], 40 | "name": "myCustomLabel", 41 | "rowspan": 1 42 | } 43 | ``` 44 | 45 | ## Table Cell with Inline Content 46 | 47 | The `contents` of a `TableCell` can contain values besides simple primitives like strings and numbers. It can store any valid [`InlineContent`](/schema/InlineContent) such as emphasized text or even images. 48 | 49 | ```json import=content 50 | { 51 | "type": "TableCell", 52 | "content": [ 53 | { 54 | "type": "Emphasis", 55 | "content": ["Some emphasized content"] 56 | } 57 | ] 58 | } 59 | ``` 60 | 61 | # Encodings 62 | 63 | include: ../docs/type-encodings-intro.md 64 | ::: 65 | This section describes common encodings for this node type. These samples are generated from the above examples by [Encoda](https://stencila.github.io/encoda), but you can also author them in each format. 66 | ::: 67 | 68 | ## JATS 69 | 70 | `TableCell` is analogous to the JATS [`<td>`](https://jats.nlm.nih.gov/articleauthoring/tag-library/1.2/element/td.html) type. While the JATS `<td>` element must be contained "in the body of a table, as opposed to a cell in the table header", the Stencila equivalent does not impose such restrictions. 71 | 72 | ## mdast 73 | 74 | `TableCell` is analogous to the mdast [`TableCell`](https://github.com/syntax-tree/mdast#tablecell) node type. 75 | 76 | ### OpenDocument 77 | 78 | `TableCell` is analogous to the OpenDocument [`<table:table-cell>`](http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1415590_253892949) element, which: 79 | 80 | > can contain paragraphs and other text content as well as sub tables. Table cells may span multiple columns and rows. Table cells may be empty. 81 | -------------------------------------------------------------------------------- /schema/TableCell.schema.yaml: -------------------------------------------------------------------------------- 1 | title: TableCell 2 | '@id': stencila:TableCell 3 | extends: Entity 4 | role: secondary 5 | status: unstable 6 | category: text 7 | description: | 8 | A cell within a `Table`. 9 | properties: 10 | name: 11 | '@id': schema:name 12 | description: The name of the cell. 13 | $comment: | 14 | Cell's have an implicit name derived from their position in the table 15 | e.g. `C4` for the cell in the third column and fourth row. However this name can be overridden 16 | with an explicit name, e.g. `rate`. 17 | type: string 18 | colspan: 19 | '@id': stencila:colspan 20 | description: | 21 | How many columns the cell extends. 22 | $comment: Based on the HTML `colspan` attribute for [table cells](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td). 23 | type: integer 24 | minimum: 0 25 | maximum: 1000 26 | default: 1 27 | cellType: 28 | '@id': stencila:cellType 29 | description: Indicates whether the cell is a header or data. 30 | $comment: | 31 | When `header`, the cell is similar to the HTML [`<th>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th)). 32 | When `data`, the cell is similar to the HTML [`<td>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td)). 33 | type: string 34 | enum: 35 | - Data 36 | - Header 37 | default: data 38 | rowspan: 39 | '@id': stencila:rowspan 40 | description: How many columns the cell extends. 41 | $comment: Based on the HTML `rowspan` attribute for [table cells](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td). 42 | type: integer 43 | minimum: 0 44 | maximum: 65534 45 | default: 1 46 | content: 47 | '@id': stencila:content 48 | description: Contents of the table cell. 49 | anyOf: 50 | - type: array 51 | items: 52 | $ref: BlockContent 53 | - type: array 54 | items: 55 | $ref: InlineContent 56 | -------------------------------------------------------------------------------- /schema/TableRow.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: TableRow 3 | authors: [] 4 | --- 5 | 6 | include: ../public/TableRow.schema.md 7 | ::: 8 | A row within a Table. 9 | 10 | | Entity | type | The name of the type and all descendant types. | string | 11 | | -------- | ----- | ---------------------------------------------- | ------ | 12 | | Entity | id | The identifier for this item. | string | 13 | | TableRow | cells | An array of cells in the row. | array | 14 | 15 | ::: 16 | 17 | A `TableRow` type is primarily a container for a list of [`Table Cell`](/schema/TableCell) types. 18 | 19 | # Examples 20 | 21 | ## Simple 22 | 23 | This is the most basic form of `TableRow` you can have, only requiring the `content` field. 24 | 25 | ```json 26 | { 27 | "type": "TableRow", 28 | "cells": [ 29 | { 30 | "type": "TableCell", 31 | "content": [1] 32 | } 33 | ] 34 | } 35 | ``` 36 | 37 | ## An Empty Row 38 | 39 | A `TableRow` can be empty and still valid, representing a table row with no data. The `content` field however, is still required. 40 | 41 | ```json 42 | { 43 | "type": "TableRow", 44 | "content": [] 45 | } 46 | ``` 47 | 48 | # Encodings 49 | 50 | include: ../docs/type-encodings-intro.md 51 | ::: 52 | This section describes common encodings for this node type. These samples are generated from the above examples by [Encoda](https://stencila.github.io/encoda), but you can also author them in each format. 53 | ::: 54 | 55 | ## JATS 56 | 57 | `TableRow` is analogous to the JATS [`<tr>`](https://jats.nlm.nih.gov/articleauthoring/tag-library/1.2/element/tr.html) type. 58 | 59 | ## mdast 60 | 61 | `TableRow` is analogous to the mdast [`TableRow`](https://github.com/syntax-tree/mdast#tablerow) node type. 62 | 63 | ## OpenDocument 64 | 65 | `TableRow` is analogous to the OpenDocument [`<table:table-row>`](http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1415588_253892949) element. 66 | -------------------------------------------------------------------------------- /schema/TableRow.schema.yaml: -------------------------------------------------------------------------------- 1 | title: TableRow 2 | '@id': stencila:TableRow 3 | extends: Entity 4 | role: secondary 5 | status: unstable 6 | category: text 7 | description: A row within a Table. 8 | properties: 9 | cells: 10 | '@id': stencila:cells 11 | description: An array of cells in the row. 12 | type: array 13 | items: 14 | $ref: TableCell 15 | rowType: 16 | '@id': stencila:rowType 17 | description: | 18 | If present, indicates that all cells in this row should be treated as header cells. 19 | type: string 20 | enum: 21 | - Header 22 | - Footer 23 | required: 24 | - cells 25 | -------------------------------------------------------------------------------- /schema/ThematicBreak.schema.yaml: -------------------------------------------------------------------------------- 1 | title: ThematicBreak 2 | '@id': stencila:ThematicBreak 3 | extends: Entity 4 | role: secondary 5 | status: stable 6 | category: text 7 | description: | 8 | A thematic break, such as a scene change in a story, a transition to another topic, or a new document. 9 | $comment: | 10 | Analogues of `ThematicBreak` in other schema include: 11 | - JATS XML [`<hr>`](https://jats.nlm.nih.gov/articleauthoring/tag-library/1.2/element/hr.html) 12 | - MDAST [`ThematicBreak`](https://github.com/syntax-tree/mdast#ThematicBreak) 13 | - OpenDocument OpenDocument [`<text:soft-page-break>`](http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#element-text_soft-page-break) 14 | properties: {} 15 | examples: 16 | - type: ThematicBreak 17 | -------------------------------------------------------------------------------- /schema/Thing.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Thing 2 | '@id': schema:Thing 3 | extends: Entity 4 | status: stable 5 | role: base 6 | category: other 7 | description: The most generic type of item. 8 | properties: 9 | alternateNames: 10 | '@id': schema:alternateName 11 | description: Alternate names (aliases) for the item. 12 | type: array 13 | items: 14 | type: string 15 | description: 16 | '@id': schema:description 17 | description: A description of the item. 18 | $comment: | 19 | Allows for the description to be an array of nodes (e.g. an array of inline content, 20 | or a couple of paragraphs), or a string. The `minItems` restriction avoids a string 21 | being coerced into an array with a single string item. 22 | anyOf: 23 | - type: array 24 | items: 25 | $ref: BlockContent 26 | - type: array 27 | items: 28 | $ref: InlineContent 29 | minItems: 2 30 | - type: string 31 | identifiers: 32 | '@id': schema:identifier 33 | description: Any kind of identifier for any kind of Thing. 34 | $comment: | 35 | Some identifiers have specific properties e.g the `issn` property for 36 | the `Periodical` type. These should be used in preference to this 37 | property which is intended for identifiers that do not yet have a 38 | specific property. Identifiers can be represented as strings, but 39 | using a `PropertyValue` will usually be better because it allows 40 | for `propertyID` (i.e. the type of identifier). 41 | type: array 42 | items: 43 | anyOf: 44 | - $ref: PropertyValue 45 | - type: string 46 | images: 47 | '@id': schema:image 48 | description: Images of the item. 49 | type: array 50 | items: 51 | anyOf: 52 | - $ref: ImageObject 53 | - type: string 54 | format: uri 55 | name: 56 | '@id': schema:name 57 | description: The name of the item. 58 | type: string 59 | url: 60 | '@id': schema:url 61 | description: The URL of the item. 62 | type: string 63 | format: uri 64 | -------------------------------------------------------------------------------- /schema/TupleValidator.schema.yaml: -------------------------------------------------------------------------------- 1 | title: TupleValidator 2 | '@id': stencila:TupleValidator 3 | extends: Validator 4 | role: validation 5 | status: unstable 6 | category: data 7 | description: A validator specifying constraints on an array of heterogeneous items. 8 | properties: 9 | items: 10 | '@id': schema:itemListElement 11 | description: An array of validators specifying the constraints on each successive item in the array. 12 | type: array 13 | items: 14 | $ref: ValidatorTypes 15 | -------------------------------------------------------------------------------- /schema/Validator.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Validator 2 | '@id': stencila:Validator 3 | extends: Entity 4 | role: validation 5 | status: unstable 6 | category: data 7 | description: A base for all validator types. 8 | $comment: | 9 | The main purpose of this type is to obtain a generated union type 10 | for all validators. 11 | -------------------------------------------------------------------------------- /schema/Variable.schema.yaml: -------------------------------------------------------------------------------- 1 | title: Variable 2 | '@id': stencila:Variable 3 | extends: Entity 4 | role: secondary 5 | status: experimental 6 | category: code 7 | description: A variable representing a name / value pair. 8 | properties: 9 | name: 10 | '@id': schema:name 11 | description: The name of the variable. 12 | type: string 13 | pattern: '[a-z_][A-z0-9_]*' 14 | $comment: | 15 | This regex allows for snake_case and camelCase names but excludes 16 | PascalCase for names. 17 | isReadonly: 18 | '@id': schema:readonlyValue 19 | description: Whether or not a property is mutable. Default is false. 20 | $comment: | 21 | If `isReadonly` is `true` and `value` is defined then changes to `value` 22 | should not be allowed. 23 | type: boolean 24 | default: false 25 | validator: 26 | '@id': stencila:validator 27 | description: The validator that the value is validated against. 28 | allOf: 29 | - $ref: ValidatorTypes 30 | value: 31 | '@id': schema:value 32 | description: The value of the variable. 33 | allOf: 34 | - $ref: Node 35 | required: 36 | - name 37 | -------------------------------------------------------------------------------- /schema/VideoObject.schema.yaml: -------------------------------------------------------------------------------- 1 | title: VideoObject 2 | '@id': schema:VideoObject 3 | extends: MediaObject 4 | category: works 5 | role: secondary 6 | status: stable 7 | description: A video file. 8 | $comment: | 9 | The `VideoObject` type allows you to provide details such as caption and transcript, 10 | and the details which are included in [`MediaObject`](./MediaObject) 11 | which `VideoObject` extends. 12 | properties: 13 | caption: 14 | '@id': schema:caption 15 | description: The caption for this video recording. 16 | type: string 17 | thumbnail: 18 | '@id': schema:thumbnail 19 | description: Thumbnail image of this video recording. 20 | allOf: 21 | - $ref: ImageObject 22 | transcript: 23 | '@id': schema:transcript 24 | description: The transcript of this video recording. 25 | type: string 26 | examples: 27 | - type: VideoObject 28 | caption: Example Video File 29 | contentSize: '45' 30 | contentUrl: http://www.example.com/file.mp4 31 | encodingFormat: video/mpeg 32 | transcript: This is the transcript for the video file... 33 | -------------------------------------------------------------------------------- /schema/VolumeMount.schema.yaml: -------------------------------------------------------------------------------- 1 | title: VolumeMount 2 | '@id': stencila:VolumeMount 3 | extends: Thing 4 | role: tertiary 5 | status: experimental 6 | category: code 7 | description: | 8 | Describes a volume mount from a host to container. 9 | properties: 10 | mountSource: 11 | '@id': stencila:mountSource 12 | description: The mount source directory on the host. 13 | type: string 14 | mountDestination: 15 | '@id': stencila:mountDestination 16 | description: The mount location inside the container. 17 | type: string 18 | mountOptions: 19 | '@id': stencila:mountOptions 20 | description: A list of options to use when applying the mount. 21 | type: array 22 | items: 23 | type: string 24 | mountType: 25 | '@id': stencila:mountType 26 | type: string 27 | description: The type of mount. 28 | required: 29 | - mountDestination 30 | -------------------------------------------------------------------------------- /ts/.gitignore: -------------------------------------------------------------------------------- 1 | docs 2 | -------------------------------------------------------------------------------- /ts/JsonSchema.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Module for defining a `JsonSchema` interface for use by other modules 3 | * in this repository e.g. generation of `*.json.schema` files by `./schema.ts`. 4 | */ 5 | 6 | import { JSONSchema7 } from 'json-schema' 7 | 8 | /** 9 | * Interface for Stencila `JsonSchema` instances. 10 | * 11 | * The `JsonSchema` interface extends JSON Schema 12 | * with additional properties for: 13 | * 14 | * - defining inheritance, 15 | * - defining property aliases 16 | * - specifying codecs used in coercion 17 | * - categorizing node types 18 | * 19 | * For more details see the guidelines for authoring schemas. 20 | */ 21 | export interface JsonSchema extends JSONSchema7 { 22 | /** 23 | * The id for the type or property schema to be used 24 | * when generating JSON-LD. 25 | */ 26 | '@id'?: string 27 | 28 | /** 29 | * The role that this schema has. 30 | */ 31 | role?: 'base' | 'primary' | 'secondary' | 'tertiary' 32 | 33 | /** 34 | * The current status of this schema. 35 | */ 36 | status?: 'experimental' | 'unstable' | 'stable' 37 | 38 | /** 39 | * The category of node that this schema belongs to. 40 | */ 41 | category?: string 42 | 43 | /** 44 | * The schema that this schema extends. 45 | */ 46 | extends?: string 47 | 48 | /** 49 | * The names of the child (direct descendants) schemas of this schema. 50 | * Added during schema processing. 51 | */ 52 | children?: string[] 53 | 54 | /** 55 | * The descendant schemas of this schema. 56 | * Added during schema processing. 57 | */ 58 | descendants?: string[] 59 | 60 | /** 61 | * The schema from which this property schema was inherited. 62 | * Only applies when used in a property of another schema. 63 | * Added during schema processing. 64 | */ 65 | from?: string 66 | 67 | /** 68 | * Is this property schema an override of a property inherited 69 | * from an ancestor. Examples of overrides include making an 70 | * optional property required, or changing the schema of the property. 71 | */ 72 | isOverride?: boolean 73 | 74 | /** 75 | * Is the property an array? 76 | */ 77 | isArray?: boolean 78 | 79 | /** 80 | * Is the property an array and have a pluralized name e.g. authors 81 | */ 82 | isPlural?: boolean 83 | 84 | /** 85 | * Aliases for this property schema. 86 | * Only applies when used in a property of another schema. 87 | */ 88 | aliases?: string[] 89 | 90 | /** 91 | * A map of property aliases. 92 | * Added during schema processing based on the `aliases` 93 | * of properties. 94 | */ 95 | propertyAliases?: { [key: string]: string } 96 | 97 | /** 98 | * The name of a parser that can be used to decode 99 | * values for this schema. 100 | */ 101 | parser?: string 102 | 103 | /** 104 | * The file in which this schema is defined. 105 | * Added during schema processing. 106 | */ 107 | file?: string 108 | 109 | /** 110 | * The source file for this schema. A URL that can be used to 111 | * provide a link to view or edit the source. 112 | */ 113 | source?: string 114 | 115 | // The following are type specializations of the 116 | // properties in `JSONSchema7` to match our usage 117 | // e.g. this `JsonSchema` is used to define `properties` 118 | // of this `JsonSchema` 119 | 120 | properties?: { [key: string]: JsonSchema } 121 | allOf?: JsonSchema[] 122 | anyOf?: JsonSchema[] 123 | items?: JsonSchema[] 124 | enum?: (string | number)[] 125 | } 126 | -------------------------------------------------------------------------------- /ts/README.md: -------------------------------------------------------------------------------- 1 | # Stencila Schema for Typescript 2 | 3 | [![Build Status](https://dev.azure.com/stencila/stencila/_apis/build/status/stencila.schema?branchName=master)](https://dev.azure.com/stencila/stencila/_build/latest?definitionId=9&branchName=master) 4 | [![Code coverage](https://badger.nokome.now.sh/codecov-folder/stencila/schema/ts)](https://codecov.io/gh/stencila/schema/tree/master/ts) 5 | [![NPM](https://img.shields.io/npm/v/@stencila/schema.svg?style=flat)](https://www.npmjs.com/package/@stencila/schema) 6 | [![Docs](https://img.shields.io/badge/docs-latest-blue.svg)](https://stencila.github.io/schema/ts/docs) 7 | 8 | This package provides Typescript bindings for the [Stencila Schema](https://schema.stenci.la). It is primarily aimed at Typescript and Javascript developers wanting to programmatically generate, or modify, executable documents. For example, it is used in [`encoda`](https://github.com/stencila/encoda), a library for converting between document formats. 9 | 10 | ## Install 11 | 12 | ```bash 13 | npm install @stencila/schema --save 14 | ``` 15 | -------------------------------------------------------------------------------- /ts/__fixtures__/invalid.Cite.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "Cite", 3 | "citationMode": "Foo", 4 | "citationIntent": ["Bar"] 5 | } 6 | -------------------------------------------------------------------------------- /ts/__fixtures__/valid.Cite.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "Cite", 3 | "target": "URL or ID of reference", 4 | "citationMode": "NarrativeAuthor", 5 | "citationIntent": ["DisagreesWith"] 6 | } 7 | -------------------------------------------------------------------------------- /ts/__tests__/helpers.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra' 2 | import path from 'path' 3 | import { JsonSchema } from '../JsonSchema' 4 | 5 | export const schema = (name: string): Promise<JsonSchema> => 6 | fs.readJSON( 7 | path.join(__dirname, '..', '..', 'public', name) 8 | ) as Promise<JsonSchema> 9 | 10 | export const snapshot = (dirname: string, name: string): string => 11 | path.join(dirname, '__file_snapshots__', name) 12 | -------------------------------------------------------------------------------- /ts/__tests__/matchers.ts: -------------------------------------------------------------------------------- 1 | import { toMatchFile } from 'jest-file-snapshot' 2 | 3 | /** 4 | * Add https://github.com/satya164/jest-file-snapshot 5 | * 6 | * > Jest matcher to write snapshots to a separate file instead of the 7 | * default snapshot file used by Jest. Writing a snapshot to a separate 8 | * file means you have proper syntax highlighting in the output file, 9 | * and better readability without those pesky escape characters. 10 | */ 11 | expect.extend({ toMatchFile }) 12 | -------------------------------------------------------------------------------- /ts/__tests__/setup.ts: -------------------------------------------------------------------------------- 1 | import { build } from '../schema' 2 | 3 | /** 4 | * Global setup run before any tests 5 | */ 6 | export default async function setup(): Promise<void> { 7 | await build() 8 | } 9 | -------------------------------------------------------------------------------- /ts/__tests__/validation.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A test based on fixtures in `../__fixtures__`. 3 | * 4 | * Tests that any fixture with a name starting with "valid" is valid 5 | * against the corresponding schema. Tests that the validation errors 6 | * associated with each file starting with "invalid" are as expected 7 | * according to snapshots. 8 | */ 9 | 10 | import Ajv from 'ajv' 11 | import addFormats from 'ajv-formats' 12 | import fs from 'fs-extra' 13 | import path from 'path' 14 | import { jsonSchemas } from '../util/jsonSchemas' 15 | 16 | let ajv: Ajv 17 | beforeAll(async () => { 18 | const schemas = await jsonSchemas() 19 | ajv = addFormats(new Ajv({ schemas, strict: false, allErrors: true })) 20 | }) 21 | 22 | const dir = path.join(__dirname, '..', '__fixtures__') 23 | const fixtures = fs.readdirSync(dir) 24 | test.each(fixtures)('%s', (filename) => { 25 | const [name, type, ext] = filename.split('.') 26 | 27 | const json = fs.readJSONSync(path.join(dir, filename)) 28 | 29 | const validate = ajv.getSchema(type) 30 | if (validate === undefined) throw new Error(`No schema for type "${type}"`) 31 | 32 | validate(json) 33 | 34 | if (name.startsWith('valid')) { 35 | expect(validate.errors).toBe(null) 36 | } else { 37 | expect(validate.errors).toMatchSnapshot() 38 | } 39 | }) 40 | -------------------------------------------------------------------------------- /ts/bindings/__file_snapshots__/BlockContent.R: -------------------------------------------------------------------------------- 1 | #' Union type for valid block content. 2 | #' 3 | #' @return A `list` of class `Union` describing valid subtypes of this type 4 | #' @export 5 | BlockContent <- Union(Claim, CodeBlock, CodeChunk, Collection, Figure, Heading, Include, List, MathBlock, Paragraph, QuoteBlock, Table, ThematicBreak) 6 | 7 | -------------------------------------------------------------------------------- /ts/bindings/__file_snapshots__/BlockContent.py: -------------------------------------------------------------------------------- 1 | """ 2 | Union type for valid block content. 3 | """ 4 | BlockContent = Union["Claim", "CodeBlock", "CodeChunk", "Collection", "Figure", "Heading", "Include", "List", "MathBlock", "Paragraph", "QuoteBlock", "Table", "ThematicBreak"] 5 | -------------------------------------------------------------------------------- /ts/bindings/__file_snapshots__/Person.R: -------------------------------------------------------------------------------- 1 | #' A person (alive, dead, undead, or fictional). 2 | #' 3 | #' @name Person 4 | #' @param address Postal address for the person. 5 | #' @param affiliations Organizations that the person is affiliated with. 6 | #' @param alternateNames Alternate names (aliases) for the item. 7 | #' @param description A description of the item. 8 | #' @param emails Email addresses for the person. 9 | #' @param familyNames Family name. In the U.S., the last name of a person. 10 | #' @param funders A person or organization that supports (sponsors) something through some kind of financial contribution. 11 | #' @param givenNames Given name. In the U.S., the first name of a person. 12 | #' @param honorificPrefix An honorific prefix preceding a person's name such as Dr/Mrs/Mr. 13 | #' @param honorificSuffix An honorific suffix after a person's name such as MD/PhD/MSCSW. 14 | #' @param id The identifier for this item. 15 | #' @param identifiers Any kind of identifier for any kind of Thing. 16 | #' @param images Images of the item. 17 | #' @param jobTitle The job title of the person (for example, Financial Manager). 18 | #' @param memberOf An organization (or program membership) to which this person belongs. 19 | #' @param meta Metadata associated with this item. 20 | #' @param name The name of the item. 21 | #' @param telephoneNumbers Telephone numbers for the person. 22 | #' @param url The URL of the item. 23 | #' @return A `list` of class `Person` 24 | #' @seealso \code{\link{Thing}} 25 | #' @export 26 | #' @examples 27 | #' Person( 28 | #' honorificPrefix = "Dr", 29 | #' givenNames = list("Jane", "J"), 30 | #' familyNames = list("Jamieson") 31 | #' ) 32 | Person <- function( 33 | address, 34 | affiliations, 35 | alternateNames, 36 | description, 37 | emails, 38 | familyNames, 39 | funders, 40 | givenNames, 41 | honorificPrefix, 42 | honorificSuffix, 43 | id, 44 | identifiers, 45 | images, 46 | jobTitle, 47 | memberOf, 48 | meta, 49 | name, 50 | telephoneNumbers, 51 | url 52 | ){ 53 | self <- Thing( 54 | alternateNames = alternateNames, 55 | description = description, 56 | id = id, 57 | identifiers = identifiers, 58 | images = images, 59 | meta = meta, 60 | name = name, 61 | url = url 62 | ) 63 | self$type <- as_scalar("Person") 64 | self[["address"]] <- check_property("Person", "address", FALSE, missing(address), Union(PostalAddress, "character"), address) 65 | self[["affiliations"]] <- check_property("Person", "affiliations", FALSE, missing(affiliations), Array(Organization), affiliations) 66 | self[["emails"]] <- check_property("Person", "emails", FALSE, missing(emails), Array("character"), emails) 67 | self[["familyNames"]] <- check_property("Person", "familyNames", FALSE, missing(familyNames), Array("character"), familyNames) 68 | self[["funders"]] <- check_property("Person", "funders", FALSE, missing(funders), Array(Union(Organization, Person)), funders) 69 | self[["givenNames"]] <- check_property("Person", "givenNames", FALSE, missing(givenNames), Array("character"), givenNames) 70 | self[["honorificPrefix"]] <- check_property("Person", "honorificPrefix", FALSE, missing(honorificPrefix), "character", honorificPrefix) 71 | self[["honorificSuffix"]] <- check_property("Person", "honorificSuffix", FALSE, missing(honorificSuffix), "character", honorificSuffix) 72 | self[["jobTitle"]] <- check_property("Person", "jobTitle", FALSE, missing(jobTitle), "character", jobTitle) 73 | self[["memberOf"]] <- check_property("Person", "memberOf", FALSE, missing(memberOf), Array(Organization), memberOf) 74 | self[["telephoneNumbers"]] <- check_property("Person", "telephoneNumbers", FALSE, missing(telephoneNumbers), Array("character"), telephoneNumbers) 75 | class(self) <- c(class(self), "Person") 76 | self 77 | } 78 | 79 | -------------------------------------------------------------------------------- /ts/bindings/__file_snapshots__/Person.py: -------------------------------------------------------------------------------- 1 | class Person(Thing): 2 | """A person (alive, dead, undead, or fictional).""" 3 | 4 | address: Optional[Union["PostalAddress", String]] = None 5 | """Postal address for the person.""" 6 | 7 | affiliations: Optional[Array["Organization"]] = None 8 | """Organizations that the person is affiliated with.""" 9 | 10 | emails: Optional[Array[String]] = None 11 | """Email addresses for the person.""" 12 | 13 | familyNames: Optional[Array[String]] = None 14 | """Family name. In the U.S., the last name of a person.""" 15 | 16 | funders: Optional[Array[Union["Organization", "Person"]]] = None 17 | """A person or organization that supports (sponsors) something through 18 | some kind of financial contribution. 19 | """ 20 | 21 | givenNames: Optional[Array[String]] = None 22 | """Given name. In the U.S., the first name of a person.""" 23 | 24 | honorificPrefix: Optional[String] = None 25 | """An honorific prefix preceding a person's name such as Dr/Mrs/Mr.""" 26 | 27 | honorificSuffix: Optional[String] = None 28 | """An honorific suffix after a person's name such as MD/PhD/MSCSW.""" 29 | 30 | jobTitle: Optional[String] = None 31 | """The job title of the person (for example, Financial Manager).""" 32 | 33 | memberOf: Optional[Array["Organization"]] = None 34 | """An organization (or program membership) to which this person belongs.""" 35 | 36 | telephoneNumbers: Optional[Array[String]] = None 37 | """Telephone numbers for the person.""" 38 | 39 | 40 | def __init__( 41 | self, 42 | address: Optional[Union["PostalAddress", String]] = None, 43 | affiliations: Optional[Array["Organization"]] = None, 44 | alternateNames: Optional[Array[String]] = None, 45 | description: Optional[Union[Array["BlockContent"], Array["InlineContent"], String]] = None, 46 | emails: Optional[Array[String]] = None, 47 | familyNames: Optional[Array[String]] = None, 48 | funders: Optional[Array[Union["Organization", "Person"]]] = None, 49 | givenNames: Optional[Array[String]] = None, 50 | honorificPrefix: Optional[String] = None, 51 | honorificSuffix: Optional[String] = None, 52 | id: Optional[String] = None, 53 | identifiers: Optional[Array[Union["PropertyValue", String]]] = None, 54 | images: Optional[Array[Union["ImageObject", String]]] = None, 55 | jobTitle: Optional[String] = None, 56 | memberOf: Optional[Array["Organization"]] = None, 57 | meta: Optional[Object] = None, 58 | name: Optional[String] = None, 59 | telephoneNumbers: Optional[Array[String]] = None, 60 | url: Optional[String] = None 61 | ) -> None: 62 | super().__init__( 63 | alternateNames=alternateNames, 64 | description=description, 65 | id=id, 66 | identifiers=identifiers, 67 | images=images, 68 | meta=meta, 69 | name=name, 70 | url=url 71 | ) 72 | if address is not None: 73 | self.address = address 74 | if affiliations is not None: 75 | self.affiliations = affiliations 76 | if emails is not None: 77 | self.emails = emails 78 | if familyNames is not None: 79 | self.familyNames = familyNames 80 | if funders is not None: 81 | self.funders = funders 82 | if givenNames is not None: 83 | self.givenNames = givenNames 84 | if honorificPrefix is not None: 85 | self.honorificPrefix = honorificPrefix 86 | if honorificSuffix is not None: 87 | self.honorificSuffix = honorificSuffix 88 | if jobTitle is not None: 89 | self.jobTitle = jobTitle 90 | if memberOf is not None: 91 | self.memberOf = memberOf 92 | if telephoneNumbers is not None: 93 | self.telephoneNumbers = telephoneNumbers 94 | -------------------------------------------------------------------------------- /ts/bindings/python.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Tests of the generation of Python language bindings 3 | * 4 | * This test suite uses file snapshots. During development 5 | * it can be useful to update the snapshots on the fly for manual inspection: 6 | * 7 | * ```bash 8 | * npx jest python.test.ts --watch --updateSnapshot 9 | * ``` 10 | */ 11 | 12 | import { classGenerator, unionGenerator } from './python' 13 | import { schema, snapshot } from '../__tests__/helpers' 14 | 15 | test('generators', async () => { 16 | expect(classGenerator(await schema('Person.schema.json'))).toMatchFile( 17 | snapshot(__dirname, 'Person.py') 18 | ) 19 | 20 | expect(unionGenerator(await schema('BlockContent.schema.json'))).toMatchFile( 21 | snapshot(__dirname, 'BlockContent.py') 22 | ) 23 | }) 24 | -------------------------------------------------------------------------------- /ts/bindings/r.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Tests of the generation of R language bindings 3 | * 4 | * This test suite uses file snapshots. During development 5 | * it can be useful to update the snapshots on the fly for manual inspection: 6 | * 7 | * ```bash 8 | * npx jest r.test.ts --watch --updateSnapshot 9 | * ``` 10 | */ 11 | 12 | import { classGenerator, enumToType, unionGenerator } from './r' 13 | import { schema, snapshot } from '../__tests__/helpers' 14 | 15 | test('generators', async () => { 16 | expect(classGenerator(await schema('Person.schema.json'))).toMatchFile( 17 | snapshot(__dirname, 'Person.R') 18 | ) 19 | 20 | expect(unionGenerator(await schema('BlockContent.schema.json'))).toMatchFile( 21 | snapshot(__dirname, 'BlockContent.R') 22 | ) 23 | 24 | const list = await schema('List.schema.json') 25 | expect(enumToType(list.properties?.order.enum ?? [])).toEqual( 26 | 'Enum("Ascending", "Descending", "Unordered")' 27 | ) 28 | }) 29 | -------------------------------------------------------------------------------- /ts/bindings/typescript.test.ts: -------------------------------------------------------------------------------- 1 | import typescript from 'typescript' 2 | import { generateTypeDefinitions } from './typescript' 3 | 4 | /** 5 | * Build `dist/types.ts` and compile it using TypeScript to 6 | * check that there are no errors. 7 | */ 8 | test('build', async () => { 9 | const file = await generateTypeDefinitions() 10 | const program = typescript.createProgram([file], {}) 11 | const diagnostics = typescript 12 | .getPreEmitDiagnostics(program) 13 | .map((diagnostic) => { 14 | return diagnostic.messageText 15 | }) 16 | expect(diagnostics).toEqual([]) 17 | }) 18 | -------------------------------------------------------------------------------- /ts/bindings/vscode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A script to update the `json.schemas` property of the `./vscode/settings.json` file. 3 | * 4 | * This enabled intellisense for files following the naming conversion of `.<type>.json`. 5 | * For example, `a.Cite.json` file will have `Cite.schema.json` applied to it within 6 | * the editor. 7 | * 8 | * @see https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings 9 | * 10 | * Run using `npx ts-node ts/bindings/vscode.ts` 11 | */ 12 | 13 | import fs from 'fs-extra' 14 | import path from 'path' 15 | import { filterInterfaceSchemas, readSchemas } from '../util/helpers' 16 | 17 | // eslint-disable-next-line @typescript-eslint/no-floating-promises 18 | ;(async () => { 19 | const mappings = filterInterfaceSchemas(await readSchemas()).map( 20 | ({ title }) => ({ 21 | fileMatch: [`*.${title ?? ''}.json`], 22 | url: `./public/${title ?? ''}.schema.json`, 23 | }) 24 | ) 25 | const file = path.join(__dirname, '..', '..', '.vscode', 'settings.json') 26 | fs.writeJsonSync( 27 | file, 28 | { ...fs.readJsonSync(file), 'json.schemas': mappings }, 29 | { spaces: 2 } 30 | ) 31 | })() 32 | -------------------------------------------------------------------------------- /ts/imports/cito.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Script to imports [Citation Typing Ontology (CiTO)](http://www.sparontologies.net/ontologies/cito) 3 | * citation types as the `CitationIntentEnumeration`. 4 | * 5 | * Fetches the CiTO JSON spec from GitHub and converts it into a type that extends `Enumeration`. 6 | * The names of citation types are all made PascalCase, linked to their CiTo `@id`, and description 7 | * copied over. 8 | * 9 | * Excludes CiTO types `Citation` and `cites` since these are already implicit in the `stencila:Cite` 10 | * type and are not a type of citation. Excludes `Likes` because it does not represent a formal citation type: 11 | * "Use of this property does NOT imply the existence of a formal citation of the entity that is 'liked'." 12 | * 13 | * Excludes `hasCitationCharacterization`, `hasCitationTimeSpan`, etc since these describe properties 14 | * of a citation other than it's type. 15 | * 16 | * Excludes `*Citation` and `Shares*` since these are related to citation "distance", not citation 17 | * intent. See https://github.com/stencila/schema/pull/260#pullrequestreview-636331806. 18 | * 19 | * Run using `npx ts-node ts/imports/cito.ts`. 20 | */ 21 | 22 | import got from 'got' 23 | import fs from 'fs-extra' 24 | import path from 'path' 25 | import { pascalCase, sentenceCase } from 'change-case' 26 | 27 | // eslint-disable-next-line @typescript-eslint/no-floating-promises 28 | ;(async () => { 29 | const { body } = await got.get( 30 | 'https://raw.githubusercontent.com/SPAROntologies/cito/b4c5b10a8d7b5f0da6ea8a4f3edcc00d7984f9a4/docs/current/cito.json', 31 | { responseType: 'json' } 32 | ) 33 | 34 | const citoUrl = 'http://purl.org/spar/cito/' 35 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 36 | const types = (body as Array<Record<string, any>>).reduce( 37 | (prev: Record<string, string>, type) => { 38 | const idUrl = type['@id'] as string 39 | 40 | if (!idUrl.startsWith(citoUrl)) return prev 41 | const id = idUrl.replace(citoUrl, '') 42 | 43 | if ( 44 | [ 45 | 'Citation', 46 | 'cites', 47 | 'hasCitationCharacterization', 48 | 'hasCitationCreationDate', 49 | 'hasCitationTimeSpan', 50 | 'hasCitedEntity', 51 | 'hasCitingEntity', 52 | 'hasCoAuthorshipCitationLevel', 53 | 'Likes', 54 | ].includes(id) || 55 | id.startsWith('Shares') || 56 | id.endsWith('Citation') 57 | ) 58 | return prev 59 | 60 | const title = pascalCase(id) 61 | // eslint-disable-next-line 62 | const rdfComment = 63 | // eslint-disable-next-line 64 | type['http://www.w3.org/2000/01/rdf-schema#comment']?.[0]?.['@value'] 65 | const description = 66 | typeof rdfComment === 'string' 67 | ? rdfComment.split('.')[0] 68 | : sentenceCase(id) 69 | 70 | const yaml = ` 71 | - const: ${title} 72 | '@id': cito:${id} 73 | description: ${description} 74 | ` 75 | return { ...prev, [title]: yaml } 76 | }, 77 | {} 78 | ) 79 | 80 | const yaml = Object.entries(types) 81 | .sort() 82 | .map(([_title, yaml]) => yaml) 83 | .join('') 84 | 85 | fs.writeFileSync( 86 | path.join( 87 | __dirname, 88 | '..', 89 | '..', 90 | 'schema', 91 | 'CitationIntentEnumeration.schema.yaml' 92 | ), 93 | `title: CitationIntentEnumeration 94 | '@id': stencila:CitationIntentEnumeration 95 | status: unstable 96 | role: secondary 97 | category: metadata 98 | extends: Enumeration 99 | description: The type or nature of a citation, both factually and rhetorically. 100 | $comment: | 101 | The members of this enumeration map directly on to the types in the [Citation Typing Ontology (CiTO)](http://www.sparontologies.net/ontologies/cito). 102 | anyOf:${yaml}` 103 | ) 104 | })() 105 | -------------------------------------------------------------------------------- /ts/index.browser.ts: -------------------------------------------------------------------------------- 1 | export * from './JsonSchema' 2 | export * from './types' 3 | export * from './util/index.browser' 4 | -------------------------------------------------------------------------------- /ts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './JsonSchema' 2 | export * from './types' 3 | export * from './util' 4 | -------------------------------------------------------------------------------- /ts/schema.test.ts: -------------------------------------------------------------------------------- 1 | import Ajv from 'ajv' 2 | import fs from 'fs-extra' 3 | import globby from 'globby' 4 | import path from 'path' 5 | import { build, readSchema } from './schema' 6 | 7 | /** 8 | * Test build function works. 9 | * 10 | * Do not cleanup to avoid interfering with 11 | * other tests that may require the schemas and that 12 | * may be running in parallel. 13 | */ 14 | test('build', async () => { 15 | await build(false) 16 | }) 17 | 18 | /** 19 | * Check that the `public/*.schema.json` files, generated from `schema/*.schema.yaml` files, 20 | * are valid JSON Schemas. 21 | */ 22 | test('schemas are valid', async () => { 23 | const ajv = new Ajv() 24 | const files = await globby( 25 | path.join(__dirname, '..', 'public', '*.schema.json') 26 | ) 27 | for (const file of files) { 28 | const schema = await fs.readJSON(file) 29 | if (ajv.validateSchema(schema) !== true) { 30 | console.log(ajv.errors) 31 | throw new Error(`💣 Oh, oh, ${file} is invalid`) 32 | } 33 | } 34 | }) 35 | 36 | /** 37 | * Test inheritance via `extend` keyword 38 | */ 39 | test('inheritance', async () => { 40 | const thing = await readSchema('Thing') 41 | const person = await readSchema('Person') 42 | 43 | /* eslint-disable @typescript-eslint/strict-boolean-expressions */ 44 | 45 | // All `Thing` properties are in `Person` properties 46 | expect( 47 | Object.keys(thing.properties ?? {}).some( 48 | (name) => !Object.keys(person.properties ?? {}).includes(name) 49 | ) 50 | ).toBe(false) 51 | 52 | // All `Thing` required properties in `Person` required properties 53 | expect( 54 | (thing.required ?? []).some( 55 | (name: string) => !(person.required ?? []).includes(name) 56 | ) 57 | ).toBe(false) 58 | 59 | // All `Thing` property aliases in `Person` property aliases 60 | expect( 61 | Object.keys(thing.propertyAliases ?? {}).some( 62 | (name) => !Object.keys(person.propertyAliases ?? {}).includes(name) 63 | ) 64 | ).toBe(false) 65 | }) 66 | -------------------------------------------------------------------------------- /ts/types.test.ts: -------------------------------------------------------------------------------- 1 | import { person, paragraph, link } from './types' 2 | 3 | describe('Schema factory functions', () => { 4 | test('no required properties', () => { 5 | expect(person()).toMatchObject({ type: 'Person' }) 6 | }) 7 | 8 | test('one required property', () => { 9 | expect( 10 | paragraph({ content: ['The content of the paragraph'] }) 11 | ).toMatchObject({ 12 | type: 'Paragraph', 13 | content: ['The content of the paragraph'], 14 | }) 15 | }) 16 | 17 | test('more than one required property', () => { 18 | expect( 19 | link({ 20 | content: ['The content of the link'], 21 | target: 'https://example.org', 22 | }) 23 | ).toMatchObject({ 24 | type: 'Link', 25 | content: ['The content of the link'], 26 | target: 'https://example.org', 27 | }) 28 | }) 29 | 30 | test('it filters undefined values from properties', () => { 31 | const actual = person({ 32 | honorificPrefix: 'Sir', 33 | honorificSuffix: undefined, 34 | givenNames: ['Isaac'], 35 | familyNames: ['Newton'], 36 | memberOf: undefined, 37 | }) 38 | 39 | expect(actual).toMatchObject({ 40 | type: 'Person', 41 | familyNames: ['Newton'], 42 | givenNames: ['Isaac'], 43 | honorificPrefix: 'Sir', 44 | }) 45 | }) 46 | }) 47 | -------------------------------------------------------------------------------- /ts/util/guards.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BlockContent, 3 | Entity, 4 | InlineContent, 5 | Node, 6 | TypeMap, 7 | Types, 8 | unions, 9 | Unions, 10 | } from '../types' 11 | 12 | export type TypeMapGeneric< 13 | T extends { type: string } & Record<string, unknown> = { type: string } 14 | > = { [key in T['type']]: key } 15 | 16 | type ExtractGeneric<Type> = Type extends TypeMap<infer X> 17 | ? X 18 | : Type extends TypeMapGeneric<infer Y> 19 | ? Y 20 | : never 21 | 22 | /** 23 | * Type guard to determine whether a node belongs to a type map 24 | * 25 | * @template {TypeMap} T 26 | * @param {T} typeMap 27 | * @param {Node} node A Stencila schema node object 28 | */ 29 | export const isInTypeMap = 30 | <T extends Partial<TypeMap | TypeMapGeneric>>(typeMap: T) => 31 | (node?: Node): node is ExtractGeneric<T> => 32 | isEntity(node) ? Object.keys(typeMap).includes(node.type) : false 33 | 34 | /** 35 | * Type guard to determine whether a node is a primitive type 36 | * (i.e. not an `Entity`). 37 | */ 38 | export const isPrimitive = ( 39 | node?: Node 40 | ): node is null | boolean | number | string => { 41 | const type = typeof node 42 | if (node === null) return true 43 | if (type === 'boolean') return true 44 | if (type === 'number') return true 45 | if (type === 'string') return true 46 | if (Array.isArray(node)) return true 47 | if (type === 'object' && !Object.prototype.hasOwnProperty.call(node, 'type')) 48 | return true 49 | return false 50 | } 51 | 52 | /** 53 | * Type guard to determine whether a node is an `Entity` 54 | */ 55 | export const isEntity = (node?: Node): node is Entity => { 56 | if (node === null || node === undefined) return false 57 | return Object.prototype.hasOwnProperty.call(node, 'type') 58 | } 59 | 60 | /** 61 | * A type guard to determine whether a node is of a specific type. 62 | * 63 | * e.g. `isA('Paragraph', node)` 64 | */ 65 | export const isA = <K extends keyof Types>( 66 | type: K, 67 | node: Node | undefined 68 | ): node is Types[K] => isEntity(node) && node.type === type 69 | 70 | /** 71 | * Returns a type guard to determine whether a node is of a specific type. 72 | * 73 | * e.g. `isType('Article')(node)` 74 | * e.g. `article.content.filter(isType('Paragraph'))` 75 | */ 76 | export const isType = 77 | <K extends keyof Types>(type: K) => 78 | (node?: Node): node is Types[K] => 79 | isA(type, node) 80 | 81 | /** 82 | * A type guard to determine whether a node is a member of a union type. 83 | * 84 | * e.g. `isIn('MediaObjectTypes', node)` 85 | */ 86 | export const isIn = <K extends keyof Unions>( 87 | union: K, 88 | node: Node | undefined 89 | ): node is Unions[K] => isEntity(node) && node.type in unions[union] 90 | 91 | /** 92 | * Returns a type guard to determine whether a node is a member of a union type. 93 | * 94 | * e.g. `isMember('CreativeWorkTypes')(node)` 95 | */ 96 | export const isMember = 97 | <K extends keyof Unions>(type: K) => 98 | (node?: Node): node is Unions[K] => 99 | isIn(type, node) 100 | 101 | /** 102 | * Type guard to determine whether a node is `InlineContent`. 103 | * 104 | * e.g. `nodes.filter(isInlineContent)` 105 | */ 106 | export const isInlineContent = (node?: Node): node is InlineContent => 107 | isPrimitive(node) || isIn('InlineContent', node) 108 | 109 | /** 110 | * Type guard to determine whether a node is `BlockContent`. 111 | * 112 | * e.g. `nodes.filter(isBlockContent)` 113 | */ 114 | export const isBlockContent = (node?: Node): node is BlockContent => 115 | isIn('BlockContent', node) 116 | -------------------------------------------------------------------------------- /ts/util/index.browser.ts: -------------------------------------------------------------------------------- 1 | export * from './guards' 2 | export * from './nodeType' 3 | export * from './version' 4 | -------------------------------------------------------------------------------- /ts/util/index.ts: -------------------------------------------------------------------------------- 1 | export * from './guards' 2 | export * from './jsonld' 3 | export * from './jsonSchemas' 4 | export * from './microdata' 5 | export * from './nodeType' 6 | export * from './version' 7 | -------------------------------------------------------------------------------- /ts/util/jsonSchemas.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | jsonSchemas, 3 | jsonSchemaTypes, 4 | jsonSchemaProperties, 5 | } from './jsonSchemas' 6 | 7 | test('jsonSchemas', async () => { 8 | const types = await jsonSchemas() 9 | expect(types).toBeInstanceOf(Object) 10 | expect(Object.keys(types).length).toBeGreaterThan(0) 11 | }) 12 | 13 | test('jsonSchemaTypes', async () => { 14 | const types = await jsonSchemaTypes() 15 | expect(types).toBeInstanceOf(Array) 16 | expect(types.length).toBeGreaterThan(0) 17 | expect(types.includes('Null')).toBeTruthy() 18 | expect(types.includes('CodeChunk')).toBeTruthy() 19 | expect(types.includes('Article')).toBeTruthy() 20 | }) 21 | 22 | test('jsonSchemaProperties', async () => { 23 | const props = await jsonSchemaProperties() 24 | expect(props).toBeInstanceOf(Object) 25 | expect(Object.keys(props).length).toBeGreaterThan(0) 26 | expect(props).toHaveProperty('authors') 27 | expect(props).toHaveProperty('honorificSuffix') 28 | }) 29 | -------------------------------------------------------------------------------- /ts/util/jsonld.test.ts: -------------------------------------------------------------------------------- 1 | import pkg from '../../package.json' 2 | import { 3 | jsonLdUrl, 4 | jsonLdContext, 5 | jsonLdTermUrl, 6 | jsonLdTermName, 7 | } from './jsonld' 8 | 9 | test('jsonLdUrl', () => { 10 | const expectedBase = `http://schema.stenci.la/v${ 11 | pkg.version.split('.')[0] 12 | }/jsonld/` 13 | 14 | expect(jsonLdUrl()).toMatch(expectedBase) 15 | expect(jsonLdUrl('CodeChunk')).toMatch(expectedBase + 'CodeChunk') 16 | expect(jsonLdUrl('outputs')).toMatch(expectedBase + 'outputs') 17 | }) 18 | 19 | test('jsonLdContext', () => { 20 | expect(jsonLdContext()).toHaveProperty('stencila') 21 | expect(jsonLdContext().stencila).toEqual(jsonLdUrl()) 22 | }) 23 | 24 | test('jsonLdTermUrl', () => { 25 | const stencilaUrl = jsonLdUrl() 26 | expect(jsonLdTermUrl('CodeChunk')).toEqual(stencilaUrl + 'CodeChunk') 27 | expect(jsonLdTermUrl('outputs')).toEqual(stencilaUrl + 'outputs') 28 | 29 | expect(jsonLdTermUrl('Article')).toEqual('http://schema.org/Article') 30 | expect(jsonLdTermUrl('authors')).toEqual('http://schema.org/author') 31 | 32 | expect(jsonLdTermUrl('foo')).toBeUndefined() 33 | }) 34 | 35 | test('jsonLdTermName', () => { 36 | const stencilaUrl = jsonLdUrl() 37 | expect(jsonLdTermName(stencilaUrl + 'CodeChunk')).toEqual('CodeChunk') 38 | expect(jsonLdTermName(stencilaUrl + 'outputs')).toEqual('outputs') 39 | 40 | expect(jsonLdTermName('http://schema.org/Article')).toEqual('Article') 41 | expect(jsonLdTermName('http://schema.org/author')).toEqual('authors') 42 | }) 43 | -------------------------------------------------------------------------------- /ts/util/nodeType.test.ts: -------------------------------------------------------------------------------- 1 | import { nodeType } from './nodeType' 2 | 3 | test('nodeType', () => { 4 | expect(nodeType(null)).toBe('Null') 5 | expect(nodeType(true)).toBe('Boolean') 6 | expect(nodeType(false)).toBe('Boolean') 7 | expect(nodeType(42)).toBe('Number') 8 | expect(nodeType(3.14)).toBe('Number') 9 | expect(nodeType('str')).toBe('String') 10 | expect(nodeType([])).toBe('Array') 11 | expect(nodeType({})).toBe('Object') 12 | expect(nodeType({ type: 'Person' })).toBe('Person') 13 | }) 14 | -------------------------------------------------------------------------------- /ts/util/nodeType.ts: -------------------------------------------------------------------------------- 1 | import { Types, Node } from '../types' 2 | import { isEntity } from './guards' 3 | 4 | /** 5 | * Get the type of a node 6 | * 7 | * @param {Node} node The schema node to get the type for 8 | */ 9 | export const nodeType = (node: Node): keyof Types => { 10 | if (node === null) return 'Null' 11 | if (typeof node === 'boolean') return 'Boolean' 12 | if (typeof node === 'number') return 'Number' 13 | if (typeof node === 'string') return 'String' 14 | if (Array.isArray(node)) return 'Array' 15 | if (isEntity(node)) return node.type 16 | return 'Object' 17 | } 18 | -------------------------------------------------------------------------------- /ts/util/version.test.ts: -------------------------------------------------------------------------------- 1 | import pkg from '../../package.json' 2 | import { version, versionMajor, versionMinor } from './version' 3 | 4 | test('version', () => { 5 | expect(version).toEqual(pkg.version) 6 | }) 7 | 8 | test('versionMajor', () => { 9 | expect(versionMajor).toEqual(pkg.version.split('.')[0]) 10 | }) 11 | 12 | test('versionMinor', () => { 13 | expect(versionMinor).toEqual(pkg.version.split('.').slice(0, 2).join('.')) 14 | }) 15 | -------------------------------------------------------------------------------- /ts/util/version.ts: -------------------------------------------------------------------------------- 1 | import { version as pkgVersion } from '../../package.json' 2 | 3 | /** 4 | * Get the version string (e.g "1.2.3") for this package 5 | */ 6 | export const version = pkgVersion 7 | 8 | /** 9 | * Get the major version string (e.g "1") for this package 10 | */ 11 | export const versionMajor: string = version.split('.')[0] 12 | 13 | /** 14 | * Get the minor version string (e.g "1.2") for this package 15 | */ 16 | export const versionMinor: string = version.split('.').slice(0, 2).join('.') 17 | -------------------------------------------------------------------------------- /tsconfig.browser.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "ESNext", 5 | "moduleResolution": "node", 6 | "lib": ["DOM", "ES2015"], 7 | "declarationDir": "dist" 8 | }, 9 | "include": ["ts/index.browser.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.docs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["ts/**/*.ts"], 4 | "exclude": ["ts/**/*.test.ts", "ts/**/__tests__", "ts/**/bindings"] 5 | } 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@stencila/dev-config/tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["DOM", "ESNext"], 5 | "moduleResolution": "node", 6 | "module": "CommonJS", 7 | "outDir": "dist" 8 | }, 9 | "include": ["ts/**/*.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "declarationDir": "dist", 6 | "module": "esnext" 7 | }, 8 | "include": ["ts/**/*.ts"], 9 | "exclude": ["ts/**/*.test.ts", "ts/**/__tests__", "ts/**/bindings"] 10 | } 11 | --------------------------------------------------------------------------------