You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@annotator.apache.org by ge...@apache.org on 2022/11/23 21:38:27 UTC
[incubator-annotator] 01/01: Create new package @apache-annotator/annotation
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 <ge...@treora.com>
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" }
]