This is an automated email from the ASF dual-hosted git repository. gerben pushed a commit to branch annotator-package in repository https://gitbox.apache.org/repos/asf/incubator-annotator.git
commit 0ebebdb3b51b6730c7253178b358d97925663298 Author: Gerben <[email protected]> AuthorDate: Wed Nov 23 22:00:40 2022 +0100 Create new package @apache-annotator/annotation Types & utility functions for annotations as a whole. With code imported from <https://code.treora.com/gerben/web-annotation-utils>. --- .../{apache-annotator => annotation}/package.json | 13 +- packages/annotation/src/index.ts | 25 +++ packages/annotation/src/multiplicity.ts | 48 +++++ packages/annotation/src/web-annotation.ts | 227 +++++++++++++++++++++ .../annotation/test/model/multiplicity.test.ts | 39 ++++ packages/{selector => annotation}/tsconfig.json | 0 packages/apache-annotator/package.json | 1 + packages/apache-annotator/src/annotation.ts | 37 ++++ packages/apache-annotator/tsconfig.json | 1 + packages/selector/src/types.ts | 21 +- packages/selector/tsconfig.json | 5 +- tsconfig.json | 1 + tsconfig.test.json | 1 + 13 files changed, 391 insertions(+), 28 deletions(-) diff --git a/packages/apache-annotator/package.json b/packages/annotation/package.json similarity index 58% copy from packages/apache-annotator/package.json copy to packages/annotation/package.json index ebec725..a663402 100644 --- a/packages/apache-annotator/package.json +++ b/packages/annotation/package.json @@ -1,22 +1,19 @@ { - "name": "apache-annotator", + "name": "@apache-annotator/annotation", "version": "0.3.0", - "description": "Apache Annotator provides annotation enabling code for browsers, servers, and humans.", + "description": "Web Annotation types and utilities.", "homepage": "https://annotator.apache.org", "repository": { "type": "git", "url": "https://github.com/apache/incubator-annotator.git", - "directory": "packages/apache-annotator" + "directory": "packages/annotation" }, "license": "Apache-2.0", "author": "Apache Software Foundation", "type": "module", - "exports": { - "./*": "./lib/*.js" - }, + "exports": "./lib/index.js", + "main": "./lib/index.js", "dependencies": { - "@apache-annotator/dom": "^0.3.0", - "@apache-annotator/selector": "^0.3.0", "@babel/runtime-corejs3": "^7.13.10" }, "engines": { diff --git a/packages/annotation/src/index.ts b/packages/annotation/src/index.ts new file mode 100644 index 0000000..1e5f467 --- /dev/null +++ b/packages/annotation/src/index.ts @@ -0,0 +1,25 @@ +/** + * @license + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * SPDX-FileCopyrightText: The Apache Software Foundation + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './web-annotation.js'; +export * from './multiplicity.js'; diff --git a/packages/annotation/src/multiplicity.ts b/packages/annotation/src/multiplicity.ts new file mode 100644 index 0000000..93a74d4 --- /dev/null +++ b/packages/annotation/src/multiplicity.ts @@ -0,0 +1,48 @@ +/** + * @license + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * SPDX-FileCopyrightText: The Apache Software Foundation + * SPDX-License-Identifier: Apache-2.0 + */ + +export type OneOrMore<T> = T | T[]; +export type ZeroOrMore<T> = undefined | null | T | T[]; + +export type OneOrMoreIncluding<Other extends any, RequiredValue extends any> = + | RequiredValue + | [RequiredValue, ...Other[]] + | [...Other[], RequiredValue]; +// | [Other, ...OneOrMoreIncluding<Other, RequiredValue>]; // FIXME TypeScript complains about the circular reference.. + +/** + * OnlyOne<T> extracts the T from a One/ZeroOrMore<T> type + */ +export type OnlyOne<T> = T extends (infer X)[] ? X : T; + +export function asArray<T>(value: ZeroOrMore<T>): T[] { + if (Array.isArray(value)) return value; + if (value === undefined || value === null) return []; + return [value]; +} + +export function asSingleValue<T>(value: ZeroOrMore<T>): T | undefined { + if (value instanceof Array) return value[0]; + if (value === undefined || value === null) return undefined; + return value; +} diff --git a/packages/annotation/src/web-annotation.ts b/packages/annotation/src/web-annotation.ts new file mode 100644 index 0000000..013abef --- /dev/null +++ b/packages/annotation/src/web-annotation.ts @@ -0,0 +1,227 @@ +/** + * @license + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * SPDX-FileCopyrightText: The Apache Software Foundation + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { + OneOrMore, + OneOrMoreIncluding, + ZeroOrMore, +} from './multiplicity.js'; + +/** + * A Web Annotation object. + * + * This is an interpretation of the Web Annotation Data Model: + * <https://www.w3.org/TR/2017/REC-annotation-model-20170223/> + * + * TODO Deal more systemically with ‘relations’, i.e. values that could be + * either a nested object or a URI referring to such an object. + */ +export interface WebAnnotation { + '@context': OneOrMoreIncluding<string, 'http://www.w3.org/ns/anno.jsonld'>; + type: OneOrMoreIncluding<string, 'Annotation'>; + id: string; + target: OneOrMore<Target>; + creator?: ZeroOrMore<Agent>; + created?: UtcDateTime; + generator?: ZeroOrMore<Agent>; + generated?: UtcDateTime; + modified?: UtcDateTime; + motivation?: ZeroOrMore<Motivation>; + audience?: ZeroOrMore<Audience>; + rights?: ZeroOrMore<string>; + canonical?: string; + via?: ZeroOrMore<string>; + body?: BodyChoice | OneOrMore<Body>; + bodyValue?: string; +} + +/** + * A slightly stricter type for WebAnnotation, not allowing both a body and bodyValue. + */ +export type WebAnnotationStrict = WebAnnotation & (WithBody | WithBodyValue | WithoutBody); + +interface WithBody { + body: BodyChoice | OneOrMore<Body>; + bodyValue?: undefined; +} + +interface WithBodyValue { + body?: undefined; + bodyValue: string; +} + +interface WithoutBody { + body?: undefined; + bodyValue?: undefined; +} + +export type Body = string | BodyObject; + +export type BodyObject = { + creator?: ZeroOrMore<Agent>; + created?: UtcDateTime; + modified?: UtcDateTime; + purpose?: ZeroOrMore<Motivation>; +} & (TextualBody | SpecificResource | ExternalResource); + +export type Target = string | SpecificResource | ExternalResource; + +export type Agent = + | string + | { + id?: string; + type?: ZeroOrMore<'Person' | 'Organization' | 'Software'>; + name?: ZeroOrMore<string>; + nickname?: ZeroOrMore<string>; + email?: ZeroOrMore<string>; + email_sha1?: ZeroOrMore<string>; + homepage?: ZeroOrMore<string>; + }; + +export type Audience = + | string + | { + id?: string; + type?: string; + }; + +export interface BodyChoice { + type: 'Choice'; + items: Body[]; +} + +export interface TextualBody extends Omit<ExternalResource, 'id' | 'type'> { + id?: string; + type: 'TextualBody'; + value: string; +} + +export interface SpecificResource { + id?: string; + type?: 'SpecificResource'; + source: string; + selector?: string | OneOrMore<Selector>; + accessibility?: AccessibilityFeatures; + rights?: ZeroOrMore<string>; + canonical?: string; + via?: ZeroOrMore<string>; +} + +/** + * A {@link https://www.w3.org/TR/2017/REC-annotation-model-20170223/#selectors + * | Selector} object of the Web Annotation Data Model. + * + * Corresponds to RDF class {@link http://www.w3.org/ns/oa#Selector} + * + * @public + */ +export interface Selector { + type?: string; + + /** + * A Selector can be refined by another Selector. + * + * See {@link https://www.w3.org/TR/2017/REC-annotation-model-20170223/#refinement-of-selection + * | §4.2.9 Refinement of Selection} in the Web Annotation Data Model. + * + * Corresponds to RDF property {@link http://www.w3.org/ns/oa#refinedBy} + */ + refinedBy?: Selector; +} + +export interface ExternalResource { + id: string; + // XXX type’s value SHOULD be one of these, “but MAY come from other vocabularies”. + type?: ZeroOrMore<'Dataset' | 'Image' | 'Video' | 'Sound' | 'Text'>; + format?: ZeroOrMore<string>; + language?: ZeroOrMore<string>; + processingLanguage?: string; + textDirection?: 'ltr' | 'rtl' | 'auto'; + accessibility?: AccessibilityFeatures; + rights?: ZeroOrMore<string>; + canonical?: string; + via?: ZeroOrMore<string>; +} + +export type Motivation = + | 'assessing' + | 'bookmarking' + | 'classifying' + | 'commenting' + | 'describing' + | 'editing' + | 'highlighting' + | 'identifying' + | 'linking' + | 'moderating' + | 'questioning' + | 'replying' + | 'tagging'; + +// “The datetime MUST be a xsd:dateTime with the UTC timezone expressed as "Z".” +type UtcDateTime = `${string}Z`; + +// To help usage, narrow the type of Date.toISOString(); it is guaranteed to end with a 'Z'. +declare global { + interface Date { + toISOString(): UtcDateTime; + } +} + +// From <https://www.w3.org/2021/a11y-discov-vocab/latest/CG-FINAL-a11y-discov-vocab-20220610.html> +export type AccessibilityFeatures = + | ZeroOrMore<AccessibilityFeature> + | 'none' + | ['none']; +export type AccessibilityFeature = + | 'annotations' + | 'ARIA' + | 'bookmarks' + | 'index' + | 'printPageNumbers' + | 'readingOrder' + | 'structuralNavigation' + | 'tableOfContents' + | 'taggedPDF' + | 'alternativeText' + | 'audioDescription' + | 'captions' + | 'describedMath' + | 'longDescription' + | 'rubyAnnotations' + | 'signLanguage' + | 'transcript' + | 'displayTransformability' + | 'synchronizedAudioText' + | 'timingControl' + | 'unlocked' + | 'ChemML' + | 'latex' + | 'MathML' + | 'ttsMarkup' + | 'highContrastAudio' + | 'highContrastDisplay' + | 'largePrint' + | 'braille' + | 'tactileGraphic' + | 'tactileObject'; diff --git a/packages/annotation/test/model/multiplicity.test.ts b/packages/annotation/test/model/multiplicity.test.ts new file mode 100644 index 0000000..6e18e10 --- /dev/null +++ b/packages/annotation/test/model/multiplicity.test.ts @@ -0,0 +1,39 @@ +/** + * @license + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * SPDX-FileCopyrightText: The Apache Software Foundation + * SPDX-License-Identifier: Apache-2.0 + */ + +import { strict as assert } from 'assert'; +import { asArray, asSingleValue } from '../../src/multiplicity'; +import type { OneOrMore, OnlyOne, ZeroOrMore } from '../../src/multiplicity'; + +describe('asArray', () => { + it('wraps a single value', () => { + const input: OneOrMore<string> = 'blub'; + const output = asArray(input); + assert.strictEqual(output, ['blub']); + }); + it('leaves an array untouched', () => { + const input: OneOrMore<string> = ['blub']; + const output = asArray(input); + assert.strictEqual(output, input); + }); +}); diff --git a/packages/selector/tsconfig.json b/packages/annotation/tsconfig.json similarity index 100% copy from packages/selector/tsconfig.json copy to packages/annotation/tsconfig.json diff --git a/packages/apache-annotator/package.json b/packages/apache-annotator/package.json index ebec725..597dd7e 100644 --- a/packages/apache-annotator/package.json +++ b/packages/apache-annotator/package.json @@ -15,6 +15,7 @@ "./*": "./lib/*.js" }, "dependencies": { + "@apache-annotator/annotation": "^0.3.0", "@apache-annotator/dom": "^0.3.0", "@apache-annotator/selector": "^0.3.0", "@babel/runtime-corejs3": "^7.13.10" diff --git a/packages/apache-annotator/src/annotation.ts b/packages/apache-annotator/src/annotation.ts new file mode 100644 index 0000000..98bc670 --- /dev/null +++ b/packages/apache-annotator/src/annotation.ts @@ -0,0 +1,37 @@ +/** + * @license + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * SPDX-FileCopyrightText: The Apache Software Foundation + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * This module provides types and utilities for the {@link https://www.w3.org/TR/2017/REC-annotation-model-20170223/ + * | Web Annotation Data Model}. + * + * Besides a type definition, it provides convenience functions for dealing with + * Web Annotations, such as getting the URL(s) of pages an annotation targets, + * or the plain text content the annotation body. It aims to provide some basic + * tools to get started writing interoperable annotation tools without having to + * deal with the intricacies of the data model. + * + * @module + */ + +export * from '@apache-annotator/annotation'; diff --git a/packages/apache-annotator/tsconfig.json b/packages/apache-annotator/tsconfig.json index 0ac1cf1..cabb91b 100644 --- a/packages/apache-annotator/tsconfig.json +++ b/packages/apache-annotator/tsconfig.json @@ -6,6 +6,7 @@ "rootDir": "src" }, "references": [ + { "path": "../annotation" }, { "path": "../dom" }, { "path": "../selector" } ] diff --git a/packages/selector/src/types.ts b/packages/selector/src/types.ts index d3c227b..afbf3b4 100644 --- a/packages/selector/src/types.ts +++ b/packages/selector/src/types.ts @@ -21,25 +21,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -/** - * A {@link https://www.w3.org/TR/2017/REC-annotation-model-20170223/#selectors - * | Selector} object of the Web Annotation Data Model. - * - * Corresponds to RDF class {@link http://www.w3.org/ns/oa#Selector} - * - * @public - */ -export interface Selector { - /** - * A Selector can be refined by another Selector. - * - * See {@link https://www.w3.org/TR/2017/REC-annotation-model-20170223/#refinement-of-selection - * | §4.2.9 Refinement of Selection} in the Web Annotation Data Model. - * - * Corresponds to RDF property {@link http://www.w3.org/ns/oa#refinedBy} - */ - refinedBy?: Selector; -} +import type { Selector } from '@apache-annotator/annotation'; +export type { Selector }; /** * The {@link https://www.w3.org/TR/2017/REC-annotation-model-20170223/#css-selector diff --git a/packages/selector/tsconfig.json b/packages/selector/tsconfig.json index 653b0a5..2281984 100644 --- a/packages/selector/tsconfig.json +++ b/packages/selector/tsconfig.json @@ -4,5 +4,8 @@ "compilerOptions": { "outDir": "lib", "rootDir": "src" - } + }, + "references": [ + { "path": "../annotation" } + ] } diff --git a/tsconfig.json b/tsconfig.json index b9a2c0d..126dcba 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "files": [], "references": [ { "path": "packages/apache-annotator" }, + { "path": "packages/annotation" }, { "path": "packages/dom" }, { "path": "packages/selector" }, { "path": "tsconfig.test.json"} diff --git a/tsconfig.test.json b/tsconfig.test.json index f439fba..0c2f128 100644 --- a/tsconfig.test.json +++ b/tsconfig.test.json @@ -2,6 +2,7 @@ "extends": "./tsconfig.base.json", "include": ["test", "packages/*/test"], "references": [ + { "path": "packages/annotation" }, { "path": "packages/dom" }, { "path": "packages/selector" } ]
