Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] export annotation set [Round 2] #2704

Open
wants to merge 28 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
403a942
update readium annotation set model [skip ci]
panaC Dec 11, 2024
bf63fe5
annotation import FIFO queue from main to reader process
panaC Dec 12, 2024
0429d08
update json schema selector
panaC Dec 12, 2024
fff4963
apache-annotator
panaC Dec 13, 2024
6fed198
lint and revert unused addAnnotationToReaderPublicatrion action previ…
panaC Dec 13, 2024
effd92e
fix seachCachePublicationResources from search to ReaderRootState at …
panaC Dec 13, 2024
c06ae34
lint and type fixes on the third-party apache-annotator lib
panaC Dec 13, 2024
05e582d
[skip ci]
panaC Dec 13, 2024
c993d56
set resourceCache to a dedicated file
panaC Dec 16, 2024
e4268a0
apache-annotator remove .js extension and fix type linting
panaC Dec 16, 2024
0304776
export annotation [skip ci]
panaC Dec 16, 2024
1c85520
import annotation
panaC Dec 16, 2024
cef265c
add textQuote in import process [skip ci]
panaC Dec 16, 2024
e6990c0
Merge branch 'develop' into feat/export-annotation-2
panaC Dec 17, 2024
87bdedc
add reader lock protection for importAnnotationSet function
panaC Dec 17, 2024
4245dc7
fix: add actionAcrossRenderer to dispatch action from renderer to
panaC Dec 18, 2024
c284410
fixes importQueue shift first elem immutability
panaC Dec 18, 2024
6a7bc53
remove unused addAnnotationToReaderPublication action
panaC Dec 18, 2024
69f4c91
lint and change xmlDom xhtml root to document.body @danielweck need …
panaC Dec 18, 2024
cd89bf0
when annotation import add locatorExtended.locations info (rangeInfo and
panaC Dec 18, 2024
a3fa129
Merge branch 'develop' into feat/export-annotation-2
danielweck Dec 20, 2024
7cf31fa
fix: add cssSelector and progressionSelector, and apply it to
panaC Dec 20, 2024
7738eab
fix: old annotation imported from updated annotation, now update the …
panaC Dec 30, 2024
b3a39cd
fix: import dialog labels
panaC Dec 30, 2024
c9184f7
fixes en/fr i18n annotation dialog
panaC Dec 30, 2024
8e9bb59
up: origin label annotation import modal
panaC Dec 30, 2024
c4b4516
Merge branch 'develop' into feat/export-annotation-2
danielweck Dec 30, 2024
29d0b52
Merge branch 'develop' into feat/export-annotation-2
danielweck Dec 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/common/models/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,16 @@ export interface WithDestination {
destination: WindowReaderDestination;
}

export interface AcrossRenderer {
sendActionAcrossRenderer: boolean;
}

// tslint:disable-next-line: max-line-length
export interface ActionWithSender<Type extends string = string, Payload = undefined, Meta = undefined> extends Action<Type, Payload, Meta>, WithSender {
}

export interface ActionWithDestination<Type extends string = string, Payload = undefined, Meta = undefined> extends Action<Type, Payload, Meta>, WithDestination {
}

export interface ActionAcrossRenderer<Type extends string = string, Payload = undefined, Meta = undefined> extends Action<Type, Payload, Meta>, AcrossRenderer {
}
269 changes: 143 additions & 126 deletions src/common/readium/annotation/annotationModel.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,18 @@
import Ajv from "ajv";
import addFormats from "ajv-formats";

export interface IReadiumAnnotationModel {
export interface IReadiumAnnotationSet {
"@context": "http://www.w3.org/ns/anno.jsonld";
id: string;
type: "AnnotationSet";
generator?: Generator;
generated?: string;
title?: string;
about: About;
items: IReadiumAnnotation[];
}

export interface IReadiumAnnotation {
"@context": "http://www.w3.org/ns/anno.jsonld";
id: string;
created: string;
Expand Down Expand Up @@ -39,15 +50,38 @@ export interface IReadiumAnnotationModel {
page?: string;
};
selector: Array<(
ITextQuoteSelector
| IProgressionSelector
| IDomRangeSelector
| IFragmentSelector
ISelector
// ITextQuoteSelector
// | ITextPositionSelector
// | IFragmentSelector
)>;
};
}

export interface ITextQuoteSelector {
export interface ISelector<T extends ISelector = undefined> {
type: string;
refinedBy?: T;
}

/**
{
"type": "TextPositionSelector",
"start": 50,
"end": 55
}
*/
export interface ITextPositionSelector extends ISelector {
type: "TextPositionSelector",
start: number,
end: number,
}
export function isTextPositionSelector(a: any): a is ITextPositionSelector {
return typeof a === "object" && a.type === "TextPositionSelector"
&& typeof a.start === "number"
&& typeof a.end === "number";
}

export interface ITextQuoteSelector extends ISelector {
type: "TextQuoteSelector";
exact: string;
prefix: string;
Expand All @@ -60,7 +94,7 @@ export function isTextQuoteSelector(a: any): a is ITextQuoteSelector {
&& typeof a.suffix === "string";
}

export interface IProgressionSelector {
export interface IProgressionSelector extends ISelector {
type: "ProgressionSelector";
value: number;
}
Expand All @@ -69,27 +103,39 @@ export function isProgressionSelector(a: any): a is IProgressionSelector {
&& typeof a.value === "number";
}

export interface IDomRangeSelector {
type: "DomRangeSelector";
startContainerElementCssSelector: string;
startContainerChildTextNodeIndex: number;
startOffset: number;
endContainerElementCssSelector: string;
endContainerChildTextNodeIndex: number;
endOffset: number;
export interface ICssSelector<T extends ISelector = any> extends ISelector<T> {
type: "CssSelector";
value: string;
}
export function isDomRangeSelector(a: any): a is IDomRangeSelector {
return typeof a === "object"
&& a.type === "DomRangeSelector"
&& typeof a.startContainerElementCssSelector === "string"
&& typeof a.startContainerChildTextNodeIndex === "number"
&& typeof a.startOffset === "number"
&& typeof a.endContainerElementCssSelector === "string"
&& typeof a.endContainerChildTextNodeIndex === "number"
&& typeof a.endOffset === "number";
export function isCssSelector(a: any): a is ICssSelector<undefined> {
return typeof a === "object" && a.type === "CssSelector"
&& typeof a.value === "string";
}

export interface IFragmentSelector {
// not used anymore
// internal DOMRange selector not shared across annotation selector
// We prefer EPUB-CFI nowadays when official library will be choosen
// export interface IDomRangeSelector {
// type: "DomRangeSelector";
// startContainerElementCssSelector: string;
// startContainerChildTextNodeIndex: number;
// startOffset: number;
// endContainerElementCssSelector: string;
// endContainerChildTextNodeIndex: number;
// endOffset: number;
// }
// export function isDomRangeSelector(a: any): a is IDomRangeSelector {
// return typeof a === "object"
// && a.type === "DomRangeSelector"
// && typeof a.startContainerElementCssSelector === "string"
// && typeof a.startContainerChildTextNodeIndex === "number"
// && typeof a.startOffset === "number"
// && typeof a.endContainerElementCssSelector === "string"
// && typeof a.endContainerChildTextNodeIndex === "number"
// && typeof a.endOffset === "number";
// }

export interface IFragmentSelector extends ISelector {
type: "FragmentSelector";
conformsTo: string;
value: string;
Expand All @@ -101,6 +147,14 @@ export function isFragmentSelector(a: any): a is IFragmentSelector {
&& typeof a.value === "string";
}

export interface ICFIFragmentSelector extends IFragmentSelector {
conformsTo: "http://www.idpf.org/epub/linking/cfi/epub-cfi.html",
}
export function isCFIFragmentSelector(a: any): a is ICFIFragmentSelector {
return isFragmentSelector(a)
&& a.conformsTo === "http://www.idpf.org/epub/linking/cfi/epub-cfi.html";
}

interface Generator {
id: string;
type: string;
Expand All @@ -117,20 +171,9 @@ interface About {
"dc:date"?: string;
}

export interface IReadiumAnnotationModelSet {
"@context": "http://www.w3.org/ns/anno.jsonld";
id: string;
type: "AnnotationSet";
generator?: Generator;
generated?: string;
title?: string;
about: About;
items: IReadiumAnnotationModel[];
}

export const readiumAnnotationModelSetJSONSchema3 = {
export const readiumAnnotationSetSchema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "IReadiumAnnotationModelSet",
"title": "IReadiumAnnotationSet",
"type": "object",
"properties": {
"@context": {
Expand Down Expand Up @@ -214,15 +257,15 @@ export const readiumAnnotationModelSetJSONSchema3 = {
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/IReadiumAnnotationModel",
"$ref": "#/definitions/IReadiumAnnotation",
},
},
},
"required": ["@context", "id", "type", "about", "items"],
"definitions": {
"IReadiumAnnotationModel": {
"IReadiumAnnotation": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "IReadiumAnnotationModelSet",
"title": "IReadiumAnnotationSet",
"type": "object",
"properties": {
"@context": {
Expand Down Expand Up @@ -340,17 +383,14 @@ export const readiumAnnotationModelSetJSONSchema3 = {
"items": {
"oneOf": [
{
"$ref": "#/definitions/ITextQuoteSelector",
},
{
"$ref": "#/definitions/IProgressionSelector",
},
{
"$ref": "#/definitions/IDomRangeSelector",
},
{
"$ref": "#/definitions/IFragmentSelector",
"$ref": "#/definitions/Selector",
},
// {
// "$ref": "#/definitions/ITextPositionSelector",
// },
// {
// "$ref": "#/definitions/IFragmentSelector",
// },
],
},
},
Expand All @@ -360,97 +400,74 @@ export const readiumAnnotationModelSetJSONSchema3 = {
},
"required": ["@context", "id", "created", "type", "target"],
},
"ITextQuoteSelector": {
"Selector": {
"type": "object",
"properties": {
"type": {
"const": "TextQuoteSelector",
},
"exact": {
"type": "string",
},
"prefix": {
"type": "string",
},
"suffix": {
"type": "string",
},
},
"required": ["type", "exact", "prefix", "suffix"],
},
"IProgressionSelector": {
"type": "object",
"properties": {
"type": {
"const": "ProgressionSelector",
},
"value": {
"type": "number",
},
},
"required": ["type", "value"],
},
"IDomRangeSelector": {
"type": "object",
"properties": {
"type": {
"const": "DomRangeSelector",
},
"startContainerElementCssSelector": {
"type": "string",
},
"startContainerChildTextNodeIndex": {
"type": "number",
},
"startOffset": {
"type": "number",
},
"endContainerElementCssSelector": {
"type": "string",
},
"endContainerChildTextNodeIndex": {
"type": "number",
},
"endOffset": {
"type": "number",
},
},
"required": [
"type",
"startContainerElementCssSelector",
"startContainerChildTextNodeIndex",
"startOffset",
"endContainerElementCssSelector",
"endContainerChildTextNodeIndex",
"endOffset",
],
},
"IFragmentSelector": {
"type": "object",
"properties": {
"type": {
"const": "FragmentSelector",
},
"conformsTo": {
"type": "string",
},
"value": {
"type": "string",
},
},
"required": ["type", "conformsTo", "value"],
"required": ["type"],
},
// "ITextQuoteSelector": {
// "type": "object",
// "properties": {
// "type": {
// "const": "TextQuoteSelector",
// },
// "exact": {
// "type": "string",
// },
// "prefix": {
// "type": "string",
// },
// "suffix": {
// "type": "string",
// },
// },
// "required": ["type", "exact", "prefix", "suffix"],
// },
// "ITextPositionSelector": {
// "type": "object",
// "properties": {
// "type": {
// "const": "TextPositionSelector",
// },
// "start": {
// "type": "number",
// },
// "end": {
// "type": "number",
// },
// },
// "required": ["type", "start", "end"],
// },
// "IFragmentSelector": {
// "type": "object",
// "properties": {
// "type": {
// "const": "FragmentSelector",
// },
// "conformsTo": {
// "type": "string",
// },
// "value": {
// "type": "string",
// },
// },
// "required": ["type", "conformsTo", "value"],
// },
},
};


export let __READIUM_ANNOTATION_AJV_ERRORS = "";
export function isIReadiumAnnotationModelSet(data: any): data is IReadiumAnnotationModelSet {
export function isIReadiumAnnotationSet(data: any): data is IReadiumAnnotationSet {

const ajv = new Ajv();
addFormats(ajv);

const valid = ajv.validate(readiumAnnotationModelSetJSONSchema3, data);
const valid = ajv.validate(readiumAnnotationSetSchema, data);

__READIUM_ANNOTATION_AJV_ERRORS = ajv.errors?.length ? JSON.stringify(ajv.errors, null, 2) : "";

Expand Down
Loading
Loading