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:48 UTC

[incubator-annotator] branch match-any-selector created (now 27650e5)

This is an automated email from the ASF dual-hosted git repository.

gerben pushed a change to branch match-any-selector
in repository https://gitbox.apache.org/repos/asf/incubator-annotator.git


      at 27650e5  Add convenience matcher functions to dom package

This branch includes the following new commits:

     new 3dad393  Create new package @apache-annotator/annotation
     new 27650e5  Add convenience matcher functions to dom package

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[incubator-annotator] 02/02: Add convenience matcher functions to dom package

Posted by ge...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gerben pushed a commit to branch match-any-selector
in repository https://gitbox.apache.org/repos/asf/incubator-annotator.git

commit 27650e59ed276e3f270ecdba33596a2565c6106d
Author: Gerben <ge...@treora.com>
AuthorDate: Wed Nov 23 22:06:26 2022 +0100

    Add convenience matcher functions to dom package
    
    - createAnySelectorMatcher mimics the signature of existing matcher creators.
    - matchSelector makes the common use case easy.
---
 packages/dom/src/index.ts |   1 +
 packages/dom/src/match.ts | 101 ++++++++++++++++++++++++++++++++++++++++++++++
 web/index.js              |  28 +------------
 3 files changed, 104 insertions(+), 26 deletions(-)

diff --git a/packages/dom/src/index.ts b/packages/dom/src/index.ts
index 6969ea9..5073811 100644
--- a/packages/dom/src/index.ts
+++ b/packages/dom/src/index.ts
@@ -21,6 +21,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+export * from './match.js';
 export * from './css.js';
 export * from './range/index.js';
 export * from './text-quote/index.js';
diff --git a/packages/dom/src/match.ts b/packages/dom/src/match.ts
new file mode 100644
index 0000000..d0038f8
--- /dev/null
+++ b/packages/dom/src/match.ts
@@ -0,0 +1,101 @@
+/**
+ * @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 { asArray, OneOrMore } from "@apache-annotator/annotation";
+import type {
+  CssSelector,
+  TextQuoteSelector,
+  TextPositionSelector,
+  RangeSelector,
+  Matcher,
+  Refinable,
+} from "@apache-annotator/selector";
+import { makeRefinable } from "@apache-annotator/selector";
+import { createCssSelectorMatcher } from "./css";
+import { makeCreateRangeSelectorMatcher } from "./range";
+import { createTextPositionSelectorMatcher } from "./text-position";
+import { createTextQuoteSelectorMatcher } from "./text-quote";
+
+export const supportedSelectorTypes = [
+  "CssSelector",
+  "TextQuoteSelector",
+  "TextPositionSelector",
+  "RangeSelector",
+];
+
+export type SupportedSelector = Refinable<
+  | CssSelector
+  | TextQuoteSelector
+  | TextPositionSelector
+  | RangeSelector<SupportedSelector>
+>;
+
+export type DomScope = Node | Range;
+export type DomMatch = Element | Range;
+export type DomMatcher = Matcher<DomScope, DomMatch>;
+
+const createMatcher: (
+  selector: SupportedSelector
+) => DomMatcher = makeRefinable<SupportedSelector, DomScope, DomMatch>(
+  (selector: SupportedSelector) => {
+    if (selector.type === "CssSelector")
+      return createCssSelectorMatcher(selector);
+    if (selector.type === "TextQuoteSelector")
+      return createTextQuoteSelectorMatcher(selector);
+    if (selector.type === "TextPositionSelector")
+      return createTextPositionSelectorMatcher(selector);
+    if (selector.type === "RangeSelector")
+      return makeCreateRangeSelectorMatcher(
+        // @ts-ignore (needless type error; bug in TypeScript?)
+        createMatcher
+      )(selector);
+    throw new Error(`Unsupported selector type: ${(selector as any)?.type}`);
+  }
+);
+
+export function createAnySelectorMatcher(
+  oneOrMoreSelectors: OneOrMore<SupportedSelector>
+): DomMatcher {
+  const selectors = asArray(oneOrMoreSelectors);
+  // Use the first selector we understand. (“Multiple Selectors SHOULD select the same content”)
+  // TODO Take the more precise one; retry with others if the first fails; perhaps combine e.g. Position+Quote for speedup.
+  const selector = selectors.find(
+    (selector) =>
+    selector.type && supportedSelectorTypes.includes(selector.type)
+  );
+  if (!selector) throw new Error(`Unsupported selector type: ${asArray(selectors).map(s => s.type)}`);
+  const matcher = createMatcher(selector as SupportedSelector)
+  return matcher;
+}
+
+export async function matchSelector(
+  selectors: OneOrMore<SupportedSelector>,
+  scope: DomScope = window.document
+) {
+  const matchGenerator = createAnySelectorMatcher(selectors)(scope);
+  const matches: DomMatch[] = [];
+  for await (const match of matchGenerator) {
+    matches.push(match);
+  }
+  return matches;
+}
diff --git a/web/index.js b/web/index.js
index 7917798..bdaa31c 100644
--- a/web/index.js
+++ b/web/index.js
@@ -24,14 +24,11 @@
 /* global info, module, source, target, form */
 
 import {
-  makeCreateRangeSelectorMatcher,
-  createTextQuoteSelectorMatcher,
+  matchSelector,
   describeTextQuote,
-  createTextPositionSelectorMatcher,
   describeTextPosition,
   highlightText,
 } from '@apache-annotator/dom';
-import { makeRefinable } from '@apache-annotator/selector';
 
 const EXAMPLE_SELECTORS = [
   {
@@ -99,29 +96,8 @@ function cleanup() {
   info.innerText = '';
 }
 
-const createMatcher = makeRefinable((selector) => {
-  const innerCreateMatcher = {
-    TextQuoteSelector: createTextQuoteSelectorMatcher,
-    TextPositionSelector: createTextPositionSelectorMatcher,
-    RangeSelector: makeCreateRangeSelectorMatcher(createMatcher),
-  }[selector.type];
-
-  if (!innerCreateMatcher) {
-    throw new Error(`Unsupported selector type: ${selector.type}`);
-  }
-
-  return innerCreateMatcher(selector);
-});
-
 async function anchor(selector) {
-  const matchAll = createMatcher(selector);
-  const ranges = [];
-
-  // First collect all matches, and only then highlight them; to avoid
-  // modifying the DOM while the matcher is running.
-  for await (const range of matchAll(target)) {
-    ranges.push(range);
-  }
+  const ranges = matchSelector(selector, target);
 
   for (const range of ranges) {
     const removeHighlight = highlightText(range);


[incubator-annotator] 01/02: Create new package @apache-annotator/annotation

Posted by ge...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gerben pushed a commit to branch match-any-selector
in repository https://gitbox.apache.org/repos/asf/incubator-annotator.git

commit 3dad393d4745b59d84875aacfc958d7426f96955
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 a93d168..455ccf6 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" }
   ]