From f74012ccb8df915b5f1001b6dfd67b4d136c5a19 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Fri, 30 Aug 2024 16:11:14 +0200 Subject: [PATCH 01/12] Simplified approach to mergeClientRects that also removes block elements (to some extent) --- .../src/utils/mergeClientRects.ts | 146 ++++++------------ 1 file changed, 45 insertions(+), 101 deletions(-) diff --git a/packages/text-annotator/src/utils/mergeClientRects.ts b/packages/text-annotator/src/utils/mergeClientRects.ts index e106fb30..1ef54351 100644 --- a/packages/text-annotator/src/utils/mergeClientRects.ts +++ b/packages/text-annotator/src/utils/mergeClientRects.ts @@ -1,105 +1,49 @@ -// The three topological relations we need to check for -type Relation = - // Inline elements, same height, directly adjacent - 'inline-adjacent' | - // Inline elements, A fully contains B - 'inline-contains' | - // Inline elements, A is fully contained inside B - 'inline-is-contained' | - // At least one block element, A fully contains B - 'block-contains' | - // At least one block element, A is fully contained in B - 'block-is-contained'; - -// Note that this is not a general topology test. Takes a -// few shortcuts to test ONLY the situations we'll encounter -// with text selections. -const getRelation = (rectA: DOMRect, rectB: DOMRect): Relation | undefined => { - const round = (num: number ) => Math.round(num * 10) / 10; - - // Some browsers have fractional pixel differences (looking at you FF!) - const a = { - top: round(rectA.top), - bottom: round(rectA.bottom), - left: round(rectA.left), - right: round(rectA.right) - }; - - const b = { - top: round(rectB.top), - bottom: round(rectB.bottom), - left: round(rectB.left), - right: round(rectB.right) - }; - - if (Math.abs(a.top - b.top) < 0.5 && Math.abs(a.bottom - b.bottom) < 0.5) { - // Same height - check for containment and adjacency - if (Math.abs(a.left - b.right) < 0.5 || Math.abs(a.right - b.left) < 0.5) - return 'inline-adjacent'; - - if (a.left >= b.left && a.right <= b.right) - return 'inline-is-contained'; - - if (a.left <= b.left && a.right >= b.right) - return 'inline-contains'; - } else { - // Different heights - check for containment - if (a.top <= b.top && a.bottom >= b.bottom) { - if (a.left <= b.left && a.right >= b.right) { - return 'block-contains' - } - } else if (a.top >= b.top && a.bottom <= b.bottom) { - if (a.left >= b.left && a.right <= b.right) { - return 'block-is-contained'; - } +// Pixels that rects can be apart vertically while still +// being considered to be on the same line. +const TOLERANCE = 3; + +export const mergeClientRects = (rects: DOMRect[]) => { + const lines: DOMRect[][] = []; + + // Sort rects from the top, to make grouping simpler + rects.sort((a, b) => a.top - b.top); + + // Group rects into lines + for (const rect of rects) { + if (lines.length === 0 || Math.abs(rect.top - lines[lines.length - 1][0].top) > TOLERANCE) { + // Start a new line + lines.push([rect]); + } else { + lines[lines.length - 1].push(rect); } } -} - -const union = (a: DOMRect, b: DOMRect): DOMRect => { - const left = Math.min(a.left, b.left); - const right = Math.max(a.right, b.right); - const top = Math.min(a.top, b.top); - const bottom = Math.max(a.bottom, b.bottom); - return new DOMRect(left, top, right - left, bottom - top); + // Merge lines + const mergedRects = lines.map(line => { + const top = Math.min(...line.map(r => r.top)); + const bottom = Math.max(...line.map(r => r.bottom)); + const left = Math.min(...line.map(r => r.left)); + const right = Math.max(...line.map(r => r.right)); + + return { + top: top, + bottom: bottom, + left: left, + right: right, + height: bottom - top, + width: right - left + } as DOMRect; + }).filter(r => r.height > 0 && r.width > 0); + + // Checks if the given rect contains any other rects + const containsOthers = (rect: DOMRect) => mergedRects.some(other => + other !== rect && + other.left >= rect.left && + other.right <= rect.right && + other.top >= rect.top && + other.bottom <= rect.bottom + ); + + // Remove all rects that contain other rects (block-level elements!) + return mergedRects.filter(rect => !containsOthers(rect)); } - -export const mergeClientRects = (rects: DOMRect[]) => rects.reduce((merged, rectA) => { - // Some browser report empty rects - discard - if (rectA.width === 0 || rectA.height === 0) - return merged; - - let next = [...merged]; - - let wasMerged = false; - - for (const rectB of merged) { - const relation = getRelation(rectA, rectB); - - if (relation === 'inline-adjacent') { - // A and B are adjacent - remove B and keep union - next = next.map(r => r === rectB ? union(rectA, rectB) : r); - wasMerged = true; - break; - } else if (relation === 'inline-contains') { - // A contains B - remove B and keep A - next = next.map(r => r === rectB ? rectA : r); - wasMerged = true; - break; - } else if (relation === 'inline-is-contained') { - // B contains A - skip A - wasMerged = true; - break; - } else if (relation === 'block-contains' || relation === 'block-is-contained') { - // Block containment - keep the element with smaller width - if (rectA.width < rectB.width) { - next = next.map(r => r === rectB ? rectA : r); - } - wasMerged = true; - break; - } - } - - return wasMerged ? next : [ ...next, rectA ]; -}, [] as DOMRect[]); From 529aeca7d70d42cac1056a18ebd9b124619e3370 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 2 Sep 2024 07:25:19 +0200 Subject: [PATCH 02/12] Dependency updates --- package-lock.json | 234 ++++++++++----------- packages/extension-tei/package.json | 4 +- packages/text-annotator-react/package.json | 6 +- packages/text-annotator/package.json | 4 +- 4 files changed, 121 insertions(+), 127 deletions(-) diff --git a/package-lock.json b/package-lock.json index 887e6f7d..bd04dbce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,20 +29,20 @@ } }, "node_modules/@annotorious/annotorious": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@annotorious/annotorious/-/annotorious-3.0.0.tgz", - "integrity": "sha512-nw6RMSGF6FiXfnNJbhJvl0NKw+2optk5fRNxkNxVICID3E3HUo1luLZadzuBmyn5RDV7iF2tDsJt558x7DxCOA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@annotorious/annotorious/-/annotorious-3.0.2.tgz", + "integrity": "sha512-kzKEciBg5IMo37NJBF0xvhLATe2r+Ax5RMbt3t+ovNTQQxs3Miuvapk19Bo44JyouCon/9xH/dKMBCa4JeiStA==", "license": "BSD-3-Clause", "dependencies": { - "@annotorious/core": "3.0.0", + "@annotorious/core": "3.0.2", "rbush": "^4.0.1", "uuid": "^10.0.0" } }, "node_modules/@annotorious/core": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@annotorious/core/-/core-3.0.0.tgz", - "integrity": "sha512-Q9HJapiMWdmrCVnets7ZEbRUn+XtlgpcHJsmkfgVWf8zO5ERmlzGIwZ4cVpm4gd+OBOeOzJiyTwFHZICv3+0iw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@annotorious/core/-/core-3.0.2.tgz", + "integrity": "sha512-jNat3SpPiJPa4Nb+CyyWiCLODzhWH08lzGGwK38eF/cvkRhsSahRGmHbFNNnr4LR/pBIteFbED98X3JOxEll4A==", "license": "BSD-3-Clause", "dependencies": { "dequal": "^2.0.3", @@ -52,13 +52,13 @@ } }, "node_modules/@annotorious/openseadragon": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@annotorious/openseadragon/-/openseadragon-3.0.0.tgz", - "integrity": "sha512-gp5dLQEngjies4vD8g1OjEAB93ZdHpuRNHtpbTEy+xrJqBfHnOv7tgdYdlbCBLBJbzNclA+QQbisOIrwIR1sAg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@annotorious/openseadragon/-/openseadragon-3.0.2.tgz", + "integrity": "sha512-o+1ph5XK8r2VwJeeDhTjQY9zvRtvmTGZwfaggohefaVwWhaNAv3iZQGZjM9minV/eXeMQbVzkxJX0P+0D1t0og==", "license": "BSD-3-Clause", "dependencies": { - "@annotorious/annotorious": "3.0.0", - "@annotorious/core": "3.0.0", + "@annotorious/annotorious": "3.0.2", + "@annotorious/core": "3.0.2", "pixi.js": "^7.4.2", "uuid": "^10.0.0" }, @@ -67,15 +67,15 @@ } }, "node_modules/@annotorious/react": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@annotorious/react/-/react-3.0.0.tgz", - "integrity": "sha512-XdwD9ojQ+aIsQqV//c3Wj1b89P84t4AY7/QDp0UjeeCxaQBIUsAwwLzysBuzzPOvWtoCk1D6zqYIyFJ3QyPRtg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@annotorious/react/-/react-3.0.2.tgz", + "integrity": "sha512-uPMqH0n91tHLIsua0UBIAaIN65apvzXJO2fhLAoVZ45doMOHe0nAeDj5FD4hee1hUAo5CefJ7XnDVLuKlPD8fw==", "license": "BSD-3-Clause", "dependencies": { - "@annotorious/annotorious": "3.0.0", - "@annotorious/core": "3.0.0", - "@annotorious/openseadragon": "3.0.0", - "@neodrag/react": "^2.0.4" + "@annotorious/annotorious": "3.0.2", + "@annotorious/core": "3.0.2", + "@annotorious/openseadragon": "3.0.2", + "@floating-ui/react": "^0.26.23" }, "peerDependencies": { "openseadragon": "^3.0.0 || ^4.0.0 || ^5.0.0", @@ -994,12 +994,6 @@ "resolve": "~1.22.2" } }, - "node_modules/@neodrag/react": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@neodrag/react/-/react-2.0.4.tgz", - "integrity": "sha512-zjqaTXAtJWEyTECVus5TRpEnLxq3jqSQRr7y4+Iu4iRczun4KixQ7vRa1yObbFi6rgrC60adEYN6kxXON8CAwA==", - "license": "MIT" - }, "node_modules/@pixi/accessibility": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/@pixi/accessibility/-/accessibility-7.4.2.tgz", @@ -1424,9 +1418,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.1.tgz", - "integrity": "sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.2.tgz", + "integrity": "sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==", "cpu": [ "arm" ], @@ -1438,9 +1432,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.1.tgz", - "integrity": "sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.2.tgz", + "integrity": "sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==", "cpu": [ "arm64" ], @@ -1452,9 +1446,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.1.tgz", - "integrity": "sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.2.tgz", + "integrity": "sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==", "cpu": [ "arm64" ], @@ -1466,9 +1460,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.1.tgz", - "integrity": "sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.2.tgz", + "integrity": "sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==", "cpu": [ "x64" ], @@ -1480,9 +1474,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.1.tgz", - "integrity": "sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.2.tgz", + "integrity": "sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==", "cpu": [ "arm" ], @@ -1494,9 +1488,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.1.tgz", - "integrity": "sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.2.tgz", + "integrity": "sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==", "cpu": [ "arm" ], @@ -1508,9 +1502,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.1.tgz", - "integrity": "sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.2.tgz", + "integrity": "sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==", "cpu": [ "arm64" ], @@ -1522,9 +1516,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.1.tgz", - "integrity": "sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.2.tgz", + "integrity": "sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==", "cpu": [ "arm64" ], @@ -1536,9 +1530,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.1.tgz", - "integrity": "sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.2.tgz", + "integrity": "sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==", "cpu": [ "ppc64" ], @@ -1550,9 +1544,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.1.tgz", - "integrity": "sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.2.tgz", + "integrity": "sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==", "cpu": [ "riscv64" ], @@ -1564,9 +1558,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.1.tgz", - "integrity": "sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.2.tgz", + "integrity": "sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==", "cpu": [ "s390x" ], @@ -1578,9 +1572,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.1.tgz", - "integrity": "sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.2.tgz", + "integrity": "sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==", "cpu": [ "x64" ], @@ -1592,9 +1586,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.1.tgz", - "integrity": "sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.2.tgz", + "integrity": "sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==", "cpu": [ "x64" ], @@ -1606,9 +1600,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.1.tgz", - "integrity": "sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.2.tgz", + "integrity": "sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==", "cpu": [ "arm64" ], @@ -1620,9 +1614,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.1.tgz", - "integrity": "sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.2.tgz", + "integrity": "sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==", "cpu": [ "ia32" ], @@ -1634,9 +1628,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.1.tgz", - "integrity": "sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.2.tgz", + "integrity": "sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==", "cpu": [ "x64" ], @@ -1878,9 +1872,9 @@ } }, "node_modules/@types/node": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.1.tgz", - "integrity": "sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==", + "version": "22.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.2.tgz", + "integrity": "sha512-acJsPTEqYqulZS/Yp/S3GgeE6GZ0qYODUR8aVr/DkhHQ8l9nd4j5x1/ZJy9/gHrRlFMqkO6i0I3E27Alu4jjPg==", "dev": true, "license": "MIT", "dependencies": { @@ -1902,9 +1896,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.4", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.4.tgz", - "integrity": "sha512-J7W30FTdfCxDDjmfRM+/JqLHBIyl7xUIp9kwK637FGmY7+mkSFSe6L4jpZzhj5QMfLssSDP4/i75AKkrdC7/Jw==", + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.5.tgz", + "integrity": "sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA==", "dev": true, "license": "MIT", "dependencies": { @@ -2390,9 +2384,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001653", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001653.tgz", - "integrity": "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw==", + "version": "1.0.30001655", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz", + "integrity": "sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==", "dev": true, "funding": [ { @@ -3563,9 +3557,9 @@ } }, "node_modules/openseadragon": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/openseadragon/-/openseadragon-4.1.1.tgz", - "integrity": "sha512-owU9gsasAcobLN+LM8lN58Xc2VDSDotY9mkrwS/NB6g9KX/PcusV4RZvhHng2RF/Q0pMziwldf62glwXoGnuzg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/openseadragon/-/openseadragon-5.0.0.tgz", + "integrity": "sha512-S9aabSjmJg7Jfow1UItR5aXiKQLtkDWyRR5fxLeqT4vSYMvfscXUDfVS9snUN3JuIrHaSPJAlR4H2DYSn5DWRg==", "license": "BSD-3-Clause", "peer": true, "funding": { @@ -3713,9 +3707,9 @@ } }, "node_modules/postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "version": "8.4.43", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.43.tgz", + "integrity": "sha512-gJAQVYbh5R3gYm33FijzCZj7CHyQ3hWMgJMprLUlIYqCwTeZhBQ19wp0e9mA25BUbEvY5+EXuuaAjqQsrBxQBQ==", "dev": true, "funding": [ { @@ -3885,9 +3879,9 @@ } }, "node_modules/rollup": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.1.tgz", - "integrity": "sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz", + "integrity": "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==", "dev": true, "license": "MIT", "dependencies": { @@ -3901,22 +3895,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.21.1", - "@rollup/rollup-android-arm64": "4.21.1", - "@rollup/rollup-darwin-arm64": "4.21.1", - "@rollup/rollup-darwin-x64": "4.21.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.1", - "@rollup/rollup-linux-arm-musleabihf": "4.21.1", - "@rollup/rollup-linux-arm64-gnu": "4.21.1", - "@rollup/rollup-linux-arm64-musl": "4.21.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.1", - "@rollup/rollup-linux-riscv64-gnu": "4.21.1", - "@rollup/rollup-linux-s390x-gnu": "4.21.1", - "@rollup/rollup-linux-x64-gnu": "4.21.1", - "@rollup/rollup-linux-x64-musl": "4.21.1", - "@rollup/rollup-win32-arm64-msvc": "4.21.1", - "@rollup/rollup-win32-ia32-msvc": "4.21.1", - "@rollup/rollup-win32-x64-msvc": "4.21.1", + "@rollup/rollup-android-arm-eabi": "4.21.2", + "@rollup/rollup-android-arm64": "4.21.2", + "@rollup/rollup-darwin-arm64": "4.21.2", + "@rollup/rollup-darwin-x64": "4.21.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.21.2", + "@rollup/rollup-linux-arm-musleabihf": "4.21.2", + "@rollup/rollup-linux-arm64-gnu": "4.21.2", + "@rollup/rollup-linux-arm64-musl": "4.21.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.21.2", + "@rollup/rollup-linux-riscv64-gnu": "4.21.2", + "@rollup/rollup-linux-s390x-gnu": "4.21.2", + "@rollup/rollup-linux-x64-gnu": "4.21.2", + "@rollup/rollup-linux-x64-musl": "4.21.2", + "@rollup/rollup-win32-arm64-msvc": "4.21.2", + "@rollup/rollup-win32-ia32-msvc": "4.21.2", + "@rollup/rollup-win32-x64-msvc": "4.21.2", "fsevents": "~2.3.2" } }, @@ -4263,9 +4257,9 @@ } }, "node_modules/tsconfck": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.1.tgz", - "integrity": "sha512-00eoI6WY57SvZEVjm13stEVE90VkEdJAFGgpFLTsZbJyW/LwFQ7uQxJHWpZ2hzSWgCPKc9AnBnNP+0X7o3hAmQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.3.tgz", + "integrity": "sha512-ulNZP1SVpRDesxeMLON/LtWM8HIgAJEIVpVVhBM6gsmvQ8+Rh+ZG7FWGvHh7Ah3pRABwVJWklWCr/BTZSv0xnQ==", "dev": true, "license": "MIT", "bin": { @@ -4489,9 +4483,9 @@ } }, "node_modules/vite-plugin-dts": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-4.0.3.tgz", - "integrity": "sha512-+xnTsaONwU2kV6zhRjtbRJSGN41uFR/whqmcb4k4fftLFDJElxthp0PP5Fq8gMeM9ytWMt1yk5gGgekLREWYQQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-4.1.0.tgz", + "integrity": "sha512-sRlmt9k2q8MrX4F2058N3KmB6WyJ3Ao6QaExOv1X99F3j0GhPziEz1zscWQ1q2r1PeFc96L7GIUu8Pl2DPr2Hg==", "dev": true, "license": "MIT", "dependencies": { @@ -4789,10 +4783,10 @@ "CETEIcean": "^1.9.3", "typescript": "5.5.4", "vite": "^5.4.2", - "vite-plugin-dts": "^4.0.3" + "vite-plugin-dts": "^4.1.0" }, "peerDependencies": { - "@annotorious/core": "^3.0.0", + "@annotorious/core": "^3.0.2", "@recogito/text-annotator": "3.0.0-rc.41" } }, @@ -4801,7 +4795,7 @@ "version": "3.0.0-rc.41", "license": "BSD-3-Clause", "dependencies": { - "@annotorious/core": "^3.0.0", + "@annotorious/core": "^3.0.2", "colord": "^2.9.3", "dequal": "^2.0.3", "rbush": "^4.0.1", @@ -4815,7 +4809,7 @@ "svelte": "^4.2.19", "typescript": "5.5.4", "vite": "^5.4.2", - "vite-plugin-dts": "^4.0.3", + "vite-plugin-dts": "^4.1.0", "vitest": "^2.0.5" } }, @@ -4824,8 +4818,8 @@ "version": "3.0.0-rc.41", "license": "BSD-3-Clause", "dependencies": { - "@annotorious/core": "^3.0.0", - "@annotorious/react": "^3.0.0", + "@annotorious/core": "^3.0.2", + "@annotorious/react": "^3.0.2", "@floating-ui/react": "^0.26.23", "@recogito/text-annotator": "3.0.0-rc.41", "@recogito/text-annotator-tei": "3.0.0-rc.41", @@ -4838,7 +4832,7 @@ "react-dom": "^18.3.1", "typescript": "5.5.4", "vite": "^5.4.2", - "vite-plugin-dts": "^4.0.3", + "vite-plugin-dts": "^4.1.0", "vite-tsconfig-paths": "^5.0.1" }, "peerDependencies": { diff --git a/packages/extension-tei/package.json b/packages/extension-tei/package.json index 084a2a9e..ed8c3959 100644 --- a/packages/extension-tei/package.json +++ b/packages/extension-tei/package.json @@ -29,10 +29,10 @@ "CETEIcean": "^1.9.3", "typescript": "5.5.4", "vite": "^5.4.2", - "vite-plugin-dts": "^4.0.3" + "vite-plugin-dts": "^4.1.0" }, "peerDependencies": { - "@annotorious/core": "^3.0.0", + "@annotorious/core": "^3.0.2", "@recogito/text-annotator": "3.0.0-rc.41" } } \ No newline at end of file diff --git a/packages/text-annotator-react/package.json b/packages/text-annotator-react/package.json index 585f81f4..abc57aa5 100644 --- a/packages/text-annotator-react/package.json +++ b/packages/text-annotator-react/package.json @@ -30,7 +30,7 @@ "react-dom": "^18.3.1", "typescript": "5.5.4", "vite": "^5.4.2", - "vite-plugin-dts": "^4.0.3", + "vite-plugin-dts": "^4.1.0", "vite-tsconfig-paths": "^5.0.1" }, "peerDependencies": { @@ -44,8 +44,8 @@ } }, "dependencies": { - "@annotorious/core": "^3.0.0", - "@annotorious/react": "^3.0.0", + "@annotorious/core": "^3.0.2", + "@annotorious/react": "^3.0.2", "@floating-ui/react": "^0.26.23", "@recogito/text-annotator": "3.0.0-rc.41", "@recogito/text-annotator-tei": "3.0.0-rc.41", diff --git a/packages/text-annotator/package.json b/packages/text-annotator/package.json index 031268bd..44561bfa 100644 --- a/packages/text-annotator/package.json +++ b/packages/text-annotator/package.json @@ -33,11 +33,11 @@ "svelte": "^4.2.19", "typescript": "5.5.4", "vite": "^5.4.2", - "vite-plugin-dts": "^4.0.3", + "vite-plugin-dts": "^4.1.0", "vitest": "^2.0.5" }, "dependencies": { - "@annotorious/core": "^3.0.0", + "@annotorious/core": "^3.0.2", "colord": "^2.9.3", "dequal": "^2.0.3", "rbush": "^4.0.1", From da0f5faf6ec6975a6cda42cea4df72e756334ff2 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 2 Sep 2024 07:26:09 +0200 Subject: [PATCH 03/12] v3.0.0-rc.42 --- package-lock.json | 22 +++++++++++----------- package.json | 2 +- packages/extension-tei/package.json | 4 ++-- packages/text-annotator-react/package.json | 6 +++--- packages/text-annotator/package.json | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index bd04dbce..ddf23f70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.41", + "version": "3.0.0-rc.42", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.41", + "version": "3.0.0-rc.42", "license": "BSD-3-Clause", "workspaces": [ "./packages/text-annotator", @@ -3557,9 +3557,9 @@ } }, "node_modules/openseadragon": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/openseadragon/-/openseadragon-5.0.0.tgz", - "integrity": "sha512-S9aabSjmJg7Jfow1UItR5aXiKQLtkDWyRR5fxLeqT4vSYMvfscXUDfVS9snUN3JuIrHaSPJAlR4H2DYSn5DWRg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/openseadragon/-/openseadragon-4.1.1.tgz", + "integrity": "sha512-owU9gsasAcobLN+LM8lN58Xc2VDSDotY9mkrwS/NB6g9KX/PcusV4RZvhHng2RF/Q0pMziwldf62glwXoGnuzg==", "license": "BSD-3-Clause", "peer": true, "funding": { @@ -4777,7 +4777,7 @@ }, "packages/extension-tei": { "name": "@recogito/text-annotator-tei", - "version": "3.0.0-rc.41", + "version": "3.0.0-rc.42", "license": "BSD-3-Clause", "devDependencies": { "CETEIcean": "^1.9.3", @@ -4787,12 +4787,12 @@ }, "peerDependencies": { "@annotorious/core": "^3.0.2", - "@recogito/text-annotator": "3.0.0-rc.41" + "@recogito/text-annotator": "3.0.0-rc.42" } }, "packages/text-annotator": { "name": "@recogito/text-annotator", - "version": "3.0.0-rc.41", + "version": "3.0.0-rc.42", "license": "BSD-3-Clause", "dependencies": { "@annotorious/core": "^3.0.2", @@ -4815,14 +4815,14 @@ }, "packages/text-annotator-react": { "name": "@recogito/react-text-annotator", - "version": "3.0.0-rc.41", + "version": "3.0.0-rc.42", "license": "BSD-3-Clause", "dependencies": { "@annotorious/core": "^3.0.2", "@annotorious/react": "^3.0.2", "@floating-ui/react": "^0.26.23", - "@recogito/text-annotator": "3.0.0-rc.41", - "@recogito/text-annotator-tei": "3.0.0-rc.41", + "@recogito/text-annotator": "3.0.0-rc.42", + "@recogito/text-annotator-tei": "3.0.0-rc.42", "CETEIcean": "^1.9.3" }, "devDependencies": { diff --git a/package.json b/package.json index 1f2562f7..b3cf0543 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.41", + "version": "3.0.0-rc.42", "description": "Recogito Text Annotator monorepo", "author": "Rainer Simon", "repository": { diff --git a/packages/extension-tei/package.json b/packages/extension-tei/package.json index ed8c3959..515948e9 100644 --- a/packages/extension-tei/package.json +++ b/packages/extension-tei/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator-tei", - "version": "3.0.0-rc.41", + "version": "3.0.0-rc.42", "description": "Recogito Text Annotator TEI extension", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -33,6 +33,6 @@ }, "peerDependencies": { "@annotorious/core": "^3.0.2", - "@recogito/text-annotator": "3.0.0-rc.41" + "@recogito/text-annotator": "3.0.0-rc.42" } } \ No newline at end of file diff --git a/packages/text-annotator-react/package.json b/packages/text-annotator-react/package.json index abc57aa5..185dc0c9 100644 --- a/packages/text-annotator-react/package.json +++ b/packages/text-annotator-react/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/react-text-annotator", - "version": "3.0.0-rc.41", + "version": "3.0.0-rc.42", "description": "Recogito Text Annotator React bindings", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -47,8 +47,8 @@ "@annotorious/core": "^3.0.2", "@annotorious/react": "^3.0.2", "@floating-ui/react": "^0.26.23", - "@recogito/text-annotator": "3.0.0-rc.41", - "@recogito/text-annotator-tei": "3.0.0-rc.41", + "@recogito/text-annotator": "3.0.0-rc.42", + "@recogito/text-annotator-tei": "3.0.0-rc.42", "CETEIcean": "^1.9.3" } } \ No newline at end of file diff --git a/packages/text-annotator/package.json b/packages/text-annotator/package.json index 44561bfa..877c5aad 100644 --- a/packages/text-annotator/package.json +++ b/packages/text-annotator/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator", - "version": "3.0.0-rc.41", + "version": "3.0.0-rc.42", "description": "A JavaScript text annotation library", "author": "Rainer Simon", "license": "BSD-3-Clause", From 7fafa46a8c3522753c9cace1027c4f02369d9a32 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 2 Sep 2024 07:53:42 +0200 Subject: [PATCH 04/12] Aligned interface between image and text popup --- .../src/TextAnnotatorPopup.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup.tsx index 6d5d9470..e93d67eb 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup.tsx @@ -15,13 +15,17 @@ import { interface TextAnnotationPopupProps { - popup(props: TextAnnotatorPopupProps): ReactNode; + popup(props: TextAnnotationPopupContentProps): ReactNode; } -export interface TextAnnotatorPopupProps { +interface TextAnnotationPopupContentProps { - selected: { annotation: TextAnnotation, editable?: boolean }[]; + annotation: TextAnnotation; + + editable?: boolean; + + event?: PointerEvent; } @@ -110,7 +114,11 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { style={floatingStyles} {...getFloatingProps()} {...getStopEventsPropagationProps()}> - {props.popup({ selected })} + {props.popup({ + annotation: selected[0].annotation, + editable: selected[0].editable, + event + })} ) : null; From e0078c1ee0265e3db84062cf39f09efb3300f53b Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 2 Sep 2024 07:54:29 +0200 Subject: [PATCH 05/12] v3.0.0-rc.43 --- package-lock.json | 16 ++++++++-------- package.json | 2 +- packages/extension-tei/package.json | 4 ++-- packages/text-annotator-react/package.json | 6 +++--- packages/text-annotator/package.json | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index ddf23f70..25f52d2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.42", + "version": "3.0.0-rc.43", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.42", + "version": "3.0.0-rc.43", "license": "BSD-3-Clause", "workspaces": [ "./packages/text-annotator", @@ -4777,7 +4777,7 @@ }, "packages/extension-tei": { "name": "@recogito/text-annotator-tei", - "version": "3.0.0-rc.42", + "version": "3.0.0-rc.43", "license": "BSD-3-Clause", "devDependencies": { "CETEIcean": "^1.9.3", @@ -4787,12 +4787,12 @@ }, "peerDependencies": { "@annotorious/core": "^3.0.2", - "@recogito/text-annotator": "3.0.0-rc.42" + "@recogito/text-annotator": "3.0.0-rc.43" } }, "packages/text-annotator": { "name": "@recogito/text-annotator", - "version": "3.0.0-rc.42", + "version": "3.0.0-rc.43", "license": "BSD-3-Clause", "dependencies": { "@annotorious/core": "^3.0.2", @@ -4815,14 +4815,14 @@ }, "packages/text-annotator-react": { "name": "@recogito/react-text-annotator", - "version": "3.0.0-rc.42", + "version": "3.0.0-rc.43", "license": "BSD-3-Clause", "dependencies": { "@annotorious/core": "^3.0.2", "@annotorious/react": "^3.0.2", "@floating-ui/react": "^0.26.23", - "@recogito/text-annotator": "3.0.0-rc.42", - "@recogito/text-annotator-tei": "3.0.0-rc.42", + "@recogito/text-annotator": "3.0.0-rc.43", + "@recogito/text-annotator-tei": "3.0.0-rc.43", "CETEIcean": "^1.9.3" }, "devDependencies": { diff --git a/package.json b/package.json index b3cf0543..5f44b22e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.42", + "version": "3.0.0-rc.43", "description": "Recogito Text Annotator monorepo", "author": "Rainer Simon", "repository": { diff --git a/packages/extension-tei/package.json b/packages/extension-tei/package.json index 515948e9..0452824c 100644 --- a/packages/extension-tei/package.json +++ b/packages/extension-tei/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator-tei", - "version": "3.0.0-rc.42", + "version": "3.0.0-rc.43", "description": "Recogito Text Annotator TEI extension", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -33,6 +33,6 @@ }, "peerDependencies": { "@annotorious/core": "^3.0.2", - "@recogito/text-annotator": "3.0.0-rc.42" + "@recogito/text-annotator": "3.0.0-rc.43" } } \ No newline at end of file diff --git a/packages/text-annotator-react/package.json b/packages/text-annotator-react/package.json index 185dc0c9..746aa850 100644 --- a/packages/text-annotator-react/package.json +++ b/packages/text-annotator-react/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/react-text-annotator", - "version": "3.0.0-rc.42", + "version": "3.0.0-rc.43", "description": "Recogito Text Annotator React bindings", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -47,8 +47,8 @@ "@annotorious/core": "^3.0.2", "@annotorious/react": "^3.0.2", "@floating-ui/react": "^0.26.23", - "@recogito/text-annotator": "3.0.0-rc.42", - "@recogito/text-annotator-tei": "3.0.0-rc.42", + "@recogito/text-annotator": "3.0.0-rc.43", + "@recogito/text-annotator-tei": "3.0.0-rc.43", "CETEIcean": "^1.9.3" } } \ No newline at end of file diff --git a/packages/text-annotator/package.json b/packages/text-annotator/package.json index 877c5aad..63c8f8fb 100644 --- a/packages/text-annotator/package.json +++ b/packages/text-annotator/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator", - "version": "3.0.0-rc.42", + "version": "3.0.0-rc.43", "description": "A JavaScript text annotation library", "author": "Rainer Simon", "license": "BSD-3-Clause", From b6dc623734e1364ce8520dbb5f02328660e0ac9a Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 2 Sep 2024 08:17:55 +0200 Subject: [PATCH 06/12] Reverted some recent changes due to breaking behavior --- .../text-annotator/src/SelectionHandler.ts | 4 +- .../src/utils/mergeClientRects.ts | 109 +++++++++++++++++- 2 files changed, 110 insertions(+), 3 deletions(-) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index 79284235..310665df 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -129,7 +129,7 @@ export const SelectionHandler = ( isLeftClick = evt.button === 0; } - document.addEventListener('pointerdown', onPointerDown); + container.addEventListener('pointerdown', onPointerDown); const onPointerUp = (evt: PointerEvent) => { const annotatable = !(evt.target as Node).parentElement?.closest(NOT_ANNOTATABLE_SELECTOR); @@ -171,7 +171,7 @@ export const SelectionHandler = ( const destroy = () => { container.removeEventListener('selectstart', onSelectStart); document.removeEventListener('selectionchange', onSelectionChange); - document.removeEventListener('pointerdown', onPointerDown); + container.removeEventListener('pointerdown', onPointerDown); document.removeEventListener('pointerup', onPointerUp); } diff --git a/packages/text-annotator/src/utils/mergeClientRects.ts b/packages/text-annotator/src/utils/mergeClientRects.ts index 1ef54351..cd7bed62 100644 --- a/packages/text-annotator/src/utils/mergeClientRects.ts +++ b/packages/text-annotator/src/utils/mergeClientRects.ts @@ -1,4 +1,110 @@ -// Pixels that rects can be apart vertically while still +// The three topological relations we need to check for +type Relation = + // Inline elements, same height, directly adjacent + 'inline-adjacent' | + // Inline elements, A fully contains B + 'inline-contains' | + // Inline elements, A is fully contained inside B + 'inline-is-contained' | + // At least one block element, A fully contains B + 'block-contains' | + // At least one block element, A is fully contained in B + 'block-is-contained'; + +// Note that this is not a general topology test. Takes a +// few shortcuts to test ONLY the situations we'll encounter +// with text selections. +const getRelation = (rectA: DOMRect, rectB: DOMRect): Relation | undefined => { + const round = (num: number ) => Math.round(num * 10) / 10; + + // Some browsers have fractional pixel differences (looking at you FF!) + const a = { + top: round(rectA.top), + bottom: round(rectA.bottom), + left: round(rectA.left), + right: round(rectA.right) + }; + + const b = { + top: round(rectB.top), + bottom: round(rectB.bottom), + left: round(rectB.left), + right: round(rectB.right) + }; + + if (Math.abs(a.top - b.top) < 0.5 && Math.abs(a.bottom - b.bottom) < 0.5) { + // Same height - check for containment and adjacency + if (Math.abs(a.left - b.right) < 0.5 || Math.abs(a.right - b.left) < 0.5) + return 'inline-adjacent'; + + if (a.left >= b.left && a.right <= b.right) + return 'inline-is-contained'; + + if (a.left <= b.left && a.right >= b.right) + return 'inline-contains'; + } else { + // Different heights - check for containment + if (a.top <= b.top && a.bottom >= b.bottom) { + if (a.left <= b.left && a.right >= b.right) { + return 'block-contains' + } + } else if (a.top >= b.top && a.bottom <= b.bottom) { + if (a.left >= b.left && a.right <= b.right) { + return 'block-is-contained'; + } + } + } +} + +const union = (a: DOMRect, b: DOMRect): DOMRect => { + const left = Math.min(a.left, b.left); + const right = Math.max(a.right, b.right); + const top = Math.min(a.top, b.top); + const bottom = Math.max(a.bottom, b.bottom); + + return new DOMRect(left, top, right - left, bottom - top); +} + +export const mergeClientRects = (rects: DOMRect[]) => rects.reduce((merged, rectA) => { + // Some browser report empty rects - discard + if (rectA.width === 0 || rectA.height === 0) + return merged; + + let next = [...merged]; + + let wasMerged = false; + + for (const rectB of merged) { + const relation = getRelation(rectA, rectB); + + if (relation === 'inline-adjacent') { + // A and B are adjacent - remove B and keep union + next = next.map(r => r === rectB ? union(rectA, rectB) : r); + wasMerged = true; + break; + } else if (relation === 'inline-contains') { + // A contains B - remove B and keep A + next = next.map(r => r === rectB ? rectA : r); + wasMerged = true; + break; + } else if (relation === 'inline-is-contained') { + // B contains A - skip A + wasMerged = true; + break; + } else if (relation === 'block-contains' || relation === 'block-is-contained') { + // Block containment - keep the element with smaller width + if (rectA.width < rectB.width) { + next = next.map(r => r === rectB ? rectA : r); + } + wasMerged = true; + break; + } + } + + return wasMerged ? next : [ ...next, rectA ]; +}, [] as DOMRect[]); + +/* Pixels that rects can be apart vertically while still // being considered to be on the same line. const TOLERANCE = 3; @@ -47,3 +153,4 @@ export const mergeClientRects = (rects: DOMRect[]) => { // Remove all rects that contain other rects (block-level elements!) return mergedRects.filter(rect => !containsOthers(rect)); } +*/ From 90337ee61541663794f3611295cc0325975d6b0a Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 2 Sep 2024 08:21:24 +0200 Subject: [PATCH 07/12] v3.0.0-rc.44 --- package-lock.json | 16 ++++++++-------- package.json | 2 +- packages/extension-tei/package.json | 4 ++-- packages/text-annotator-react/package.json | 6 +++--- packages/text-annotator/package.json | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 25f52d2e..383ffa5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.43", + "version": "3.0.0-rc.44", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.43", + "version": "3.0.0-rc.44", "license": "BSD-3-Clause", "workspaces": [ "./packages/text-annotator", @@ -4777,7 +4777,7 @@ }, "packages/extension-tei": { "name": "@recogito/text-annotator-tei", - "version": "3.0.0-rc.43", + "version": "3.0.0-rc.44", "license": "BSD-3-Clause", "devDependencies": { "CETEIcean": "^1.9.3", @@ -4787,12 +4787,12 @@ }, "peerDependencies": { "@annotorious/core": "^3.0.2", - "@recogito/text-annotator": "3.0.0-rc.43" + "@recogito/text-annotator": "3.0.0-rc.44" } }, "packages/text-annotator": { "name": "@recogito/text-annotator", - "version": "3.0.0-rc.43", + "version": "3.0.0-rc.44", "license": "BSD-3-Clause", "dependencies": { "@annotorious/core": "^3.0.2", @@ -4815,14 +4815,14 @@ }, "packages/text-annotator-react": { "name": "@recogito/react-text-annotator", - "version": "3.0.0-rc.43", + "version": "3.0.0-rc.44", "license": "BSD-3-Clause", "dependencies": { "@annotorious/core": "^3.0.2", "@annotorious/react": "^3.0.2", "@floating-ui/react": "^0.26.23", - "@recogito/text-annotator": "3.0.0-rc.43", - "@recogito/text-annotator-tei": "3.0.0-rc.43", + "@recogito/text-annotator": "3.0.0-rc.44", + "@recogito/text-annotator-tei": "3.0.0-rc.44", "CETEIcean": "^1.9.3" }, "devDependencies": { diff --git a/package.json b/package.json index 5f44b22e..a5867b69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.43", + "version": "3.0.0-rc.44", "description": "Recogito Text Annotator monorepo", "author": "Rainer Simon", "repository": { diff --git a/packages/extension-tei/package.json b/packages/extension-tei/package.json index 0452824c..8a266a47 100644 --- a/packages/extension-tei/package.json +++ b/packages/extension-tei/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator-tei", - "version": "3.0.0-rc.43", + "version": "3.0.0-rc.44", "description": "Recogito Text Annotator TEI extension", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -33,6 +33,6 @@ }, "peerDependencies": { "@annotorious/core": "^3.0.2", - "@recogito/text-annotator": "3.0.0-rc.43" + "@recogito/text-annotator": "3.0.0-rc.44" } } \ No newline at end of file diff --git a/packages/text-annotator-react/package.json b/packages/text-annotator-react/package.json index 746aa850..0312a715 100644 --- a/packages/text-annotator-react/package.json +++ b/packages/text-annotator-react/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/react-text-annotator", - "version": "3.0.0-rc.43", + "version": "3.0.0-rc.44", "description": "Recogito Text Annotator React bindings", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -47,8 +47,8 @@ "@annotorious/core": "^3.0.2", "@annotorious/react": "^3.0.2", "@floating-ui/react": "^0.26.23", - "@recogito/text-annotator": "3.0.0-rc.43", - "@recogito/text-annotator-tei": "3.0.0-rc.43", + "@recogito/text-annotator": "3.0.0-rc.44", + "@recogito/text-annotator-tei": "3.0.0-rc.44", "CETEIcean": "^1.9.3" } } \ No newline at end of file diff --git a/packages/text-annotator/package.json b/packages/text-annotator/package.json index 63c8f8fb..7e9d17dc 100644 --- a/packages/text-annotator/package.json +++ b/packages/text-annotator/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator", - "version": "3.0.0-rc.43", + "version": "3.0.0-rc.44", "description": "A JavaScript text annotation library", "author": "Rainer Simon", "license": "BSD-3-Clause", From dd19e39bfb1734fc3ae43fbf77accab0852910f7 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 2 Sep 2024 09:34:27 +0200 Subject: [PATCH 08/12] Cleanup --- .../text-annotator/src/SelectionHandler.ts | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index 310665df..29a55f4f 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -54,9 +54,6 @@ export const SelectionHandler = ( } } - if (annotatingEnabled) - container.addEventListener('selectstart', onSelectStart); - const onSelectionChange = debounce((evt: PointerEvent) => { const sel = document.getSelection(); @@ -113,10 +110,7 @@ export const SelectionHandler = ( // select events don't have offsetX/offsetY - reuse last up/down) selection.userSelect(currentTarget.annotation, lastPointerDown); } - }) - - if (annotatingEnabled) - document.addEventListener('selectionchange', onSelectionChange); + }); // Select events don't carry information about the mouse button // Therefore, to prevent right-click selection, we need to listen @@ -129,8 +123,6 @@ export const SelectionHandler = ( isLeftClick = evt.button === 0; } - container.addEventListener('pointerdown', onPointerDown); - const onPointerUp = (evt: PointerEvent) => { const annotatable = !(evt.target as Node).parentElement?.closest(NOT_ANNOTATABLE_SELECTOR); if (!annotatable || !isLeftClick) @@ -166,13 +158,20 @@ export const SelectionHandler = ( } } + container.addEventListener('pointerdown', onPointerDown); document.addEventListener('pointerup', onPointerUp); + if (annotatingEnabled) { + container.addEventListener('selectstart', onSelectStart); + document.addEventListener('selectionchange', onSelectionChange); + } + const destroy = () => { - container.removeEventListener('selectstart', onSelectStart); - document.removeEventListener('selectionchange', onSelectionChange); container.removeEventListener('pointerdown', onPointerDown); document.removeEventListener('pointerup', onPointerUp); + + container.removeEventListener('selectstart', onSelectStart); + document.removeEventListener('selectionchange', onSelectionChange); } return { From 855a53ddbc44c9efd7ec8ac8da407fe0fc610cf2 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 2 Sep 2024 10:38:17 +0200 Subject: [PATCH 09/12] Re-export tweak --- packages/text-annotator/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/text-annotator/src/index.ts b/packages/text-annotator/src/index.ts index 4ca291f0..ace37ae9 100644 --- a/packages/text-annotator/src/index.ts +++ b/packages/text-annotator/src/index.ts @@ -25,6 +25,7 @@ export type { ParseResult, User, UserSelectActionExpression, + ViewportState, W3CAnnotation, W3CAnnotationBody, W3CAnnotationTarget From b036292a39392d72918c900f9a3bf56f3c24f22f Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 2 Sep 2024 14:12:15 +0200 Subject: [PATCH 10/12] TS tweaks --- packages/text-annotator/src/highlight/baseRenderer.ts | 4 ++-- packages/text-annotator/src/highlight/span/spansRenderer.ts | 4 ++-- packages/text-annotator/src/index.ts | 1 + packages/text-annotator/src/state/TextAnnotationStore.ts | 2 ++ packages/text-annotator/src/state/TextAnnotatorState.ts | 3 +++ 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/text-annotator/src/highlight/baseRenderer.ts b/packages/text-annotator/src/highlight/baseRenderer.ts index 3698c4dd..67d9b59b 100644 --- a/packages/text-annotator/src/highlight/baseRenderer.ts +++ b/packages/text-annotator/src/highlight/baseRenderer.ts @@ -44,9 +44,9 @@ export interface Renderer { } -export const createBaseRenderer = ( +export const createBaseRenderer = ( container: HTMLElement, - state: TextAnnotatorState, + state: T, viewport: ViewportState, renderer: RendererImplementation ): Renderer => { diff --git a/packages/text-annotator/src/highlight/span/spansRenderer.ts b/packages/text-annotator/src/highlight/span/spansRenderer.ts index 47dd7f13..eb9d052b 100644 --- a/packages/text-annotator/src/highlight/span/spansRenderer.ts +++ b/packages/text-annotator/src/highlight/span/spansRenderer.ts @@ -114,8 +114,8 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { } -export const createSpansRenderer = ( +export const createSpansRenderer = ( container: HTMLElement, - state: TextAnnotatorState, + state: T, viewport: ViewportState ) => createBaseRenderer(container, state, viewport, createRenderer(container)); diff --git a/packages/text-annotator/src/index.ts b/packages/text-annotator/src/index.ts index ace37ae9..8cfb3b69 100644 --- a/packages/text-annotator/src/index.ts +++ b/packages/text-annotator/src/index.ts @@ -3,6 +3,7 @@ export * from './model'; export * from './state'; export * from './utils'; export * from './presence/PresencePainterOptions'; +export * from './SelectionHandler'; export * from './TextAnnotator'; export * from './TextAnnotatorOptions'; diff --git a/packages/text-annotator/src/state/TextAnnotationStore.ts b/packages/text-annotator/src/state/TextAnnotationStore.ts index c8c643db..06dbf78f 100644 --- a/packages/text-annotator/src/state/TextAnnotationStore.ts +++ b/packages/text-annotator/src/state/TextAnnotationStore.ts @@ -13,6 +13,8 @@ export interface TextAnnotationStore extends Omit, 'addAnn getAnnotationBounds(id: string, hintX?: number, hintY?: number, buffer?: number): DOMRect; + getAnnotationRects(id: string): DOMRect[]; + getAt(x: number, y: number, filter?: Filter): TextAnnotation | undefined; getIntersecting(minX: number, minY: number, maxX: number, maxY: number): AnnotationRects[]; diff --git a/packages/text-annotator/src/state/TextAnnotatorState.ts b/packages/text-annotator/src/state/TextAnnotatorState.ts index c1e044f0..2d602e36 100644 --- a/packages/text-annotator/src/state/TextAnnotatorState.ts +++ b/packages/text-annotator/src/state/TextAnnotatorState.ts @@ -130,6 +130,8 @@ export const createTextAnnotatorState = ( return tree.getAnnotationBounds(id); } + const getAnnotationRects = (id: string): DOMRect[] => tree.getAnnotationRects(id); + const recalculatePositions = () => tree.recalculate(); store.observe(({ changes }) => { @@ -155,6 +157,7 @@ export const createTextAnnotatorState = ( bulkUpdateTargets, bulkUpsertAnnotations, getAnnotationBounds, + getAnnotationRects, getAt, getIntersecting: tree.getIntersecting, recalculatePositions, From 992dd6771f3c01c1156446536001802b87823d39 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 2 Sep 2024 15:16:10 +0200 Subject: [PATCH 11/12] More TypeScript flexibility --- .../src/state/TextAnnotationStore.ts | 14 +++++++------- .../text-annotator/src/state/TextAnnotatorState.ts | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/text-annotator/src/state/TextAnnotationStore.ts b/packages/text-annotator/src/state/TextAnnotationStore.ts index 06dbf78f..e64fb0f2 100644 --- a/packages/text-annotator/src/state/TextAnnotationStore.ts +++ b/packages/text-annotator/src/state/TextAnnotationStore.ts @@ -1,15 +1,15 @@ import type { Filter, Origin, Store } from '@annotorious/core'; import type { TextAnnotation } from '../model'; -export interface TextAnnotationStore extends Omit, 'addAnnotation' | 'bulkAddAnnotation'> { +export interface TextAnnotationStore extends Omit, 'addAnnotation' | 'bulkAddAnnotation'> { // Minor changes to default Annotorious store - text store returns feedback // on annotations that failed to render, to support lazy document loading scenarios - addAnnotation(annotation: TextAnnotation, origin?: Origin): boolean; + addAnnotation(annotation: T, origin?: Origin): boolean; - bulkAddAnnotation(annotations: TextAnnotation[], replace: boolean, origin?: Origin): TextAnnotation[]; + bulkAddAnnotation(annotations: T[], replace: boolean, origin?: Origin): T[]; - bulkUpsertAnnotations(annotations: TextAnnotation[], origin?: Origin): TextAnnotation[]; + bulkUpsertAnnotations(annotations: T[], origin?: Origin): T[]; getAnnotationBounds(id: string, hintX?: number, hintY?: number, buffer?: number): DOMRect; @@ -17,15 +17,15 @@ export interface TextAnnotationStore extends Omit, 'addAnn getAt(x: number, y: number, filter?: Filter): TextAnnotation | undefined; - getIntersecting(minX: number, minY: number, maxX: number, maxY: number): AnnotationRects[]; + getIntersecting(minX: number, minY: number, maxX: number, maxY: number): AnnotationRects[]; recalculatePositions(): void; } -export interface AnnotationRects { +export interface AnnotationRects { - annotation: TextAnnotation; + annotation: T; rects: Rect[]; diff --git a/packages/text-annotator/src/state/TextAnnotatorState.ts b/packages/text-annotator/src/state/TextAnnotatorState.ts index 2d602e36..e2a889a2 100644 --- a/packages/text-annotator/src/state/TextAnnotatorState.ts +++ b/packages/text-annotator/src/state/TextAnnotatorState.ts @@ -14,9 +14,9 @@ import type { TextAnnotation, TextAnnotationTarget } from '../model'; import type { TextAnnotationStore } from './TextAnnotationStore'; import { isRevived, reviveAnnotation, reviveTarget } from '../utils'; -export interface TextAnnotatorState extends AnnotatorState { +export interface TextAnnotatorState extends AnnotatorState { - store: TextAnnotationStore; + store: TextAnnotationStore; selection: SelectionState; From c6d2c9b1b564e41a6d749763ceceed038c40d406 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 2 Sep 2024 16:32:46 +0200 Subject: [PATCH 12/12] Formatting --- packages/text-annotator/src/state/spatialTree.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/text-annotator/src/state/spatialTree.ts b/packages/text-annotator/src/state/spatialTree.ts index 675ffe76..9260c3e9 100644 --- a/packages/text-annotator/src/state/spatialTree.ts +++ b/packages/text-annotator/src/state/spatialTree.ts @@ -76,7 +76,6 @@ export const createSpatialTree = (store: Store, container: HTMLE const insert = (target: TextAnnotationTarget) => { const rects = toItems(target, container.getBoundingClientRect()); - rects.forEach(rect => tree.insert(rect)); index.set(target.annotation, rects); }