Skip to content

Commit

Permalink
Merge branch 'refs/heads/main' into recogito#103-redraw-export
Browse files Browse the repository at this point in the history
# Conflicts:
#	packages/text-annotator/src/TextAnnotator.ts
  • Loading branch information
oleksandr-danylchenko committed Jul 9, 2024
2 parents 932f585 + fbe29fd commit 183d229
Show file tree
Hide file tree
Showing 35 changed files with 667 additions and 591 deletions.
738 changes: 376 additions & 362 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@recogito/text-annotator-monorepo",
"version": "3.0.0-rc.29",
"version": "3.0.0-rc.35",
"description": "Recogito Text Annotator monorepo",
"author": "Rainer Simon",
"repository": {
Expand Down
12 changes: 6 additions & 6 deletions packages/extension-tei/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@recogito/text-annotator-tei",
"version": "3.0.0-rc.29",
"version": "3.0.0-rc.35",
"description": "Recogito Text Annotator TEI extension",
"author": "Rainer Simon",
"license": "BSD-3-Clause",
Expand All @@ -26,13 +26,13 @@
"./dist/text-annotator.css": "./dist/text-annotator-tei.css"
},
"devDependencies": {
"CETEIcean": "^1.9.2",
"typescript": "^5.4.5",
"vite": "^5.2.12",
"CETEIcean": "^1.9.3",
"typescript": "^5.5.2",
"vite": "^5.3.1",
"vite-plugin-dts": "^3.9.1"
},
"peerDependencies": {
"@annotorious/core": "^3.0.0-rc.27",
"@recogito/text-annotator": "3.0.0-rc.29"
"@annotorious/core": "^3.0.0-rc.30",
"@recogito/text-annotator": "3.0.0-rc.35"
}
}
4 changes: 2 additions & 2 deletions packages/extension-tei/src/TEIPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const TEIPlugin = (anno: TextAnnotator): RecogitoTEIAnnotator => {
const _addAnnotation = store.addAnnotation;
store.addAnnotation = (annotation: TEIAnnotation | TextAnnotation, origin: Origin) => {
const { selector } = annotation.target;
return ('startSelector' in selector) ?
return ('startSelector' in selector && 'start' in selector) ?
_addAnnotation(annotation, origin) :
_addAnnotation(toTEI(annotation), origin);
}
Expand All @@ -56,7 +56,7 @@ export const TEIPlugin = (anno: TextAnnotator): RecogitoTEIAnnotator => {
store.bulkAddAnnotation = (annotations: Array<TEIAnnotation | TextAnnotation>, replace = true, origin: Origin) => {
const teiAnnotations = annotations.map(a => {
const { selector } = a.target;
return 'startSelector' in selector ? a : toTEI(a);
return ('startSelector' in selector && 'start' in selector) ? a : toTEI(a);
});

return _bulkAddAnnotation(teiAnnotations, replace, origin);
Expand Down
55 changes: 53 additions & 2 deletions packages/extension-tei/src/crosswalk/forward.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isRevived, reviveTarget } from '@recogito/text-annotator';
import { rangeToSelector, reviveTarget as reviveTextOffsetTarget } from '@recogito/text-annotator';
import type {
TextAnnotation,
TextAnnotationTarget,
Expand Down Expand Up @@ -105,11 +105,62 @@ export const textToTEISelector = (selector: TextSelector): TEIRangeSelector => {
type: 'XPathSelector',
value: end
},
quote: selector.quote.replace(/\s+/g, ' '),
quote: selector.quote?.replace(/\s+/g, ' '),
range
};
}

export const reviveTarget = (t: TextAnnotationTarget, container: HTMLElement) => {
const selector = Array.isArray(t.selector) ? t.selector[0] : t.selector;

if ('start' in selector && 'end' in selector) {
return reviveTextOffsetTarget(t, container);
} else {
const startExpression = (selector as TEIRangeSelector).startSelector?.value;
const endExpression = (selector as TEIRangeSelector).endSelector?.value;

if (!startExpression || !endExpression) {
console.error(t);
throw 'Could not revive TEI target.'
}

const evaluateSelector = (value: string) => {
const splitIdx = value.indexOf('::');

if (splitIdx < 0) return;

const path = value.substring(0, splitIdx).replace(/\/([^[/]+)/g, (_, p1) => {
return '/tei-' + p1.toLowerCase();
}).replace(/xml:/g, '');

const node = document.evaluate('.' + path,
container, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

const offset = parseInt(value.substring(splitIdx + 2));

return [node, offset] as [Node, number];
}

const [startNode, startOffset] = evaluateSelector(startExpression);
const [endNode, endOffset] = evaluateSelector(endExpression);

const range = document.createRange();
range.setStart(startNode.firstChild, startOffset);
range.setEnd(endNode.firstChild, endOffset);

const textSelector = rangeToSelector(range, container);

return reviveTextOffsetTarget({
...t,
selector: [{
...textSelector,
...(selector as TEIRangeSelector),
range
}]
}, container);
}
}

export const textToTEITarget = (container: HTMLElement) => (t: TextAnnotationTarget): TEIAnnotationTarget => {
const target = reviveTarget(t, container);
return {
Expand Down
1 change: 1 addition & 0 deletions packages/extension-tei/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './TEIAnnotation';
export * from './TEIPlugin';
5 changes: 1 addition & 4 deletions packages/extension-tei/test/annotations.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@
"target": {
"annotation": "5430edac-706b-4943-9b87-fd6e8f281b39",
"selector": [{
"start": 3436,
"startSelector": {
"type": "XPathSelector",
"value": "//castItem[@xml:id='WITCHES_Mac']::13"
},
"end": 5102,
"endSelector": {
"type": "XPathSelector",
"value": "//castItem[@xml:id='Ross_Mac']/role[1]/name[1]::4"
},
"quote": "Three Witches, the Weïrd Sisters Duncan king of Scotland Malcolm his elder son Donalbain Duncan’s younger son Macbeth thane of Glamis Lady Macbeth Seyton attendant to Macbeth Three Murderers in Macbeth’s service both attending upon Lady Macbeth A Doctor A Gentlewoman A Porter Banquo commander, with Macbeth, of Duncan’s army Fleance his son Macduff a Scottish noble Lady Macduff Their son Scottish Nobles Lennox Ross"
}
}],
"creator": {
"isGuest": true,
Expand Down
2 changes: 0 additions & 2 deletions packages/extension-tei/test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
console.log('updateAnnotation', annotation);
});

/*
anno.on('deleteAnnotation', (annotation) => {
console.log('deleteAnnotation', annotation);
});
Expand All @@ -82,7 +81,6 @@
anno.on('viewportIntersect', (annotations) => {
console.log('viewport', annotations);
});
*/
});
}
</script>
Expand Down
20 changes: 10 additions & 10 deletions packages/text-annotator-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@recogito/react-text-annotator",
"version": "3.0.0-rc.29",
"version": "3.0.0-rc.35",
"description": "Recogito Text Annotator React bindings",
"author": "Rainer Simon",
"license": "BSD-3-Clause",
Expand All @@ -25,12 +25,12 @@
"types": "./dist/index.d.ts",
"devDependencies": {
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.0",
"@vitejs/plugin-react": "^4.3.1",
"openseadragon": "4.1.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"typescript": "^5.4.5",
"vite": "^5.2.12",
"typescript": "^5.5.2",
"vite": "^5.3.1",
"vite-plugin-dts": "^3.9.1",
"vite-tsconfig-paths": "^4.3.2"
},
Expand All @@ -45,11 +45,11 @@
}
},
"dependencies": {
"@annotorious/core": "^3.0.0-rc.27",
"@annotorious/react": "^3.0.0-rc.27",
"@floating-ui/react": "^0.26.15",
"@recogito/text-annotator": "3.0.0-rc.29",
"@recogito/text-annotator-tei": "3.0.0-rc.29",
"CETEIcean": "^1.9.2"
"@annotorious/core": "^3.0.0-rc.30",
"@annotorious/react": "^3.0.0-rc.30",
"@floating-ui/react": "^0.26.18",
"@recogito/text-annotator": "3.0.0-rc.35",
"@recogito/text-annotator-tei": "3.0.0-rc.35",
"CETEIcean": "^1.9.3"
}
}
2 changes: 1 addition & 1 deletion packages/text-annotator-react/src/TextAnnotatorPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,4 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => {
</div>
)

}
}
7 changes: 7 additions & 0 deletions packages/text-annotator-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,10 @@ export type {
export {
W3CTextFormat
} from '@recogito/text-annotator';

export type {
RecogitoTEIAnnotator,
TEIAnnotation,
TEIAnnotationTarget,
TEIRangeSelector
} from '@recogito/text-annotator-tei';
35 changes: 18 additions & 17 deletions packages/text-annotator-react/test/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,37 @@ import { TextAnnotation, TextAnnotator as RecogitoTextAnnotator, W3CTextFormat }
const TestPopup = (props: TextAnnotatorPopupProps) => {

const store = useAnnotationStore();

const el = useRef<HTMLDivElement>(null);

const anno = useAnnotator<RecogitoTextAnnotator>();

const inputRef = useRef<HTMLInputElement | null>(null);

const body: AnnotationBody = {
id: `${Math.random()}`,
annotation: props.selected[0].annotation.id,
purpose: 'commenting',
value: 'A Dummy Comment'
}
};

const onClick = () => {
store.addBody(body);
anno.state.selection.clear();
}
anno.cancelSelected();
};

useEffect(() => {
window.setTimeout(() =>
el.current?.querySelector('input')!.focus(), 1);
const { current: inputEl } = inputRef;
if (!inputEl) return;

setTimeout(() => inputEl.focus({ preventScroll: true }));
}, []);

return (
<div ref={el} className="popup">
<input type="text" />
<div className="popup">
<input ref={inputRef} type="text" />
<button onClick={onClick}>Close</button>
</div>
)
);

}
};

const MockStorage = () => {

Expand All @@ -61,12 +62,12 @@ const MockStorage = () => {
anno.off('deleteAnnotation', handleDeleteAnnotation);
anno.off('selectionChanged', handleSelectionChanged);
anno.off('updateAnnotation', handleUpdateAnnotation);
}
};
}, [anno]);

return null;

}
};

export const App = () => {
const w3cAdapter = useCallback((container: HTMLElement) => W3CTextFormat('https://www.gutenberg.org', container), []);
Expand Down Expand Up @@ -201,8 +202,8 @@ export const App = () => {
}
/>

<MockStorage/>
<MockStorage />
</Annotorious>
)
);

}
};
44 changes: 27 additions & 17 deletions packages/text-annotator-react/test/tei/App.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,44 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';

import { AnnotationBody, Annotorious, useAnnotationStore, useAnnotator } from '@annotorious/react';
import { CETEIcean, TextAnnotatorPopup, TextAnnotatorPopupProps } from '../../src';
import { TextAnnotation, TextAnnotator as VanillaTextAnnotator } from '@recogito/text-annotator';
import { TEIAnnotator } from '../../src';

import { TEIAnnotator, CETEIcean, TextAnnotatorPopup, TextAnnotatorPopupProps } from '../../src';

const TestPopup = (props: TextAnnotatorPopupProps) => {

const store = useAnnotationStore();

const anno = useAnnotator<VanillaTextAnnotator>();

const inputRef = useRef<HTMLInputElement | null>(null);

const body: AnnotationBody = {
id: `${Math.random()}`,
annotation: props.selected[0].annotation.id,
purpose: 'commenting',
value: 'A Dummy Comment'
}
};

const onClick = () => {
store.addBody(body);
anno.state.selection.clear();
}
anno.cancelSelected();
};

useEffect(() => {
const { current: inputEl } = inputRef;
if (!inputEl) return;

setTimeout(() => inputEl.focus({ preventScroll: true }));
}, []);

return (
<div className="popup">
<input type="text" />
<input ref={inputRef} type="text" />
<button onClick={onClick}>Close</button>
</div>
)
);

}
};

const MockStorage = () => {

Expand All @@ -44,11 +53,11 @@ const MockStorage = () => {
anno.on('deleteAnnotation', (annotation: TextAnnotation) => {
console.log('delete', annotation);
});

anno.on('selectionChanged', (annotations: TextAnnotation[]) => {
console.log('selection changed', annotations);
});

anno.on('updateAnnotation', (annotation: TextAnnotation, previous: TextAnnotation) => {
console.log('update', annotation, previous);
});
Expand All @@ -57,7 +66,7 @@ const MockStorage = () => {

return null;

}
};

export const App = () => {

Expand All @@ -74,14 +83,15 @@ export const App = () => {
<TEIAnnotator>
<CETEIcean tei={tei} />

<TextAnnotatorPopup
<TextAnnotatorPopup
popup={props => (
<TestPopup {...props} />
)} />
)}
/>

<MockStorage />
</TEIAnnotator>
</Annotorious>
)
);

}
};
Loading

0 comments on commit 183d229

Please sign in to comment.