@semiont/api-client 0.2.45 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
- import { components, ResourceUri } from '@semiont/core';
1
+ import { components, Selector } from '@semiont/core';
2
+ export { Selector, getFragmentSelector, getSvgSelector, getTextPositionSelector, validateSvgMarkup } from '@semiont/core';
2
3
 
3
4
  /**
4
5
  * Annotation and Selector Utilities
@@ -18,13 +19,12 @@ type TextPositionSelector = components['schemas']['TextPositionSelector'];
18
19
  type TextQuoteSelector = components['schemas']['TextQuoteSelector'];
19
20
  type SvgSelector = components['schemas']['SvgSelector'];
20
21
  type FragmentSelector = components['schemas']['FragmentSelector'];
21
- type Selector = TextPositionSelector | TextQuoteSelector | SvgSelector | FragmentSelector;
22
22
 
23
23
  /**
24
24
  * Get the source from an annotation body (null if stub)
25
25
  * Search for SpecificResource in body array
26
26
  */
27
- declare function getBodySource(body: Annotation['body']): ResourceUri | null;
27
+ declare function getBodySource(body: Annotation['body']): string | null;
28
28
  /**
29
29
  * Get the type from an annotation body (returns first body type in array)
30
30
  */
@@ -37,7 +37,7 @@ declare function isBodyResolved(body: Annotation['body']): boolean;
37
37
  /**
38
38
  * Get the source IRI from target (handles both string and object forms)
39
39
  */
40
- declare function getTargetSource(target: Annotation['target']): ResourceUri;
40
+ declare function getTargetSource(target: Annotation['target']): string;
41
41
  /**
42
42
  * Get the selector from target (undefined if string or no selector)
43
43
  */
@@ -134,42 +134,12 @@ declare function getAnnotationExactText(annotation: Annotation): string;
134
134
  * When selector is a single object, returns it as-is.
135
135
  */
136
136
  declare function getPrimarySelector(selector: Selector | Selector[]): Selector;
137
- /**
138
- * Get TextPositionSelector from a selector (single or array)
139
- *
140
- * Returns the first TextPositionSelector found, or null if none exists.
141
- * Handles undefined selector (when target is a string IRI with no selector)
142
- */
143
- declare function getTextPositionSelector(selector: Selector | Selector[] | undefined): TextPositionSelector | null;
144
137
  /**
145
138
  * Get TextQuoteSelector from a selector (single or array)
146
139
  *
147
140
  * Returns the first TextQuoteSelector found, or null if none exists.
148
141
  */
149
142
  declare function getTextQuoteSelector(selector: Selector | Selector[]): TextQuoteSelector | null;
150
- /**
151
- * Get SvgSelector from a selector (single or array)
152
- *
153
- * Returns the first SvgSelector found, or null if none exists.
154
- */
155
- declare function getSvgSelector(selector: Selector | Selector[] | undefined): SvgSelector | null;
156
- /**
157
- * Get FragmentSelector from a selector (single or array)
158
- *
159
- * Returns the first FragmentSelector found, or null if none exists.
160
- */
161
- declare function getFragmentSelector(selector: Selector | Selector[] | undefined): FragmentSelector | null;
162
- /**
163
- * Validate SVG markup for W3C compliance
164
- *
165
- * Checks that:
166
- * - SVG contains xmlns attribute
167
- * - SVG is well-formed XML
168
- * - SVG contains at least one shape element
169
- *
170
- * @returns null if valid, error message if invalid
171
- */
172
- declare function validateSvgMarkup(svg: string): string | null;
173
143
  /**
174
144
  * Extract bounding box from SVG markup
175
145
  *
@@ -304,11 +274,7 @@ type Representation = components['schemas']['Representation'];
304
274
  /**
305
275
  * Get the resource ID from @id property
306
276
  *
307
- * For internal resources: extracts UUID from "http://localhost:4000/resources/{uuid}"
308
- * For external resources: returns undefined
309
- *
310
- * This is used for routing - the frontend URL should contain only the resource ID,
311
- * not the full HTTP URI.
277
+ * @id is always a bare ID (UUID), never a full URI.
312
278
  */
313
279
  declare function getResourceId(resource: ResourceDescriptor | undefined): string | undefined;
314
280
  /**
@@ -615,4 +581,4 @@ declare function validateData<T>(schema: {
615
581
  */
616
582
  declare function isValidEmail(email: string): boolean;
617
583
 
618
- export { type BoundingBox, type ContentCache, type FragmentSelector, JWTTokenSchema, LOCALES, type LocaleInfo, type MatchQuality, type Point, type Selector, type SvgSelector, type TextPosition, type TextPositionSelector, type TextQuoteSelector, type ValidatedAnnotation, type ValidationFailure, type ValidationResult, type ValidationSuccess, buildContentCache, createCircleSvg, createPolygonSvg, createRectangleSvg, decodeRepresentation, decodeWithCharset, extractBoundingBox, extractCharset, extractContext, findBestTextMatch, findTextWithContext, formatLocaleDisplay, getAllLocaleCodes, getAnnotationExactText, getBodySource, getBodyType, getChecksum, getCommentText, getCreator, getDerivedFrom, getExactText, getFragmentSelector, getLanguage, getLocaleEnglishName, getLocaleInfo, getLocaleNativeName, getNodeEncoding, getPrimaryMediaType, getPrimaryRepresentation, getPrimarySelector, getResourceEntityTypes, getResourceId, getStorageUri, getSvgSelector, getTargetSelector, getTargetSource, getTextPositionSelector, getTextQuoteSelector, hasTargetSelector, isArchived, isAssessment, isBodyResolved, isComment, isDraft, isHighlight, isReference, isResolvedReference, isStubReference, isTag, isValidEmail, normalizeCoordinates, normalizeText, parseSvgSelector, scaleSvgToNative, validateAndCorrectOffsets, validateData, validateSvgMarkup, verifyPosition };
584
+ export { type BoundingBox, type ContentCache, type FragmentSelector, JWTTokenSchema, LOCALES, type LocaleInfo, type MatchQuality, type Point, type SvgSelector, type TextPosition, type TextPositionSelector, type TextQuoteSelector, type ValidatedAnnotation, type ValidationFailure, type ValidationResult, type ValidationSuccess, buildContentCache, createCircleSvg, createPolygonSvg, createRectangleSvg, decodeRepresentation, decodeWithCharset, extractBoundingBox, extractCharset, extractContext, findBestTextMatch, findTextWithContext, formatLocaleDisplay, getAllLocaleCodes, getAnnotationExactText, getBodySource, getBodyType, getChecksum, getCommentText, getCreator, getDerivedFrom, getExactText, getLanguage, getLocaleEnglishName, getLocaleInfo, getLocaleNativeName, getNodeEncoding, getPrimaryMediaType, getPrimaryRepresentation, getPrimarySelector, getResourceEntityTypes, getResourceId, getStorageUri, getTargetSelector, getTargetSource, getTextQuoteSelector, hasTargetSelector, isArchived, isAssessment, isBodyResolved, isComment, isDraft, isHighlight, isReference, isResolvedReference, isStubReference, isTag, isValidEmail, normalizeCoordinates, normalizeText, parseSvgSelector, scaleSvgToNative, validateAndCorrectOffsets, validateData, verifyPosition };
@@ -1,4 +1,4 @@
1
- import { resourceUri } from '@semiont/core';
1
+ export { getFragmentSelector, getSvgSelector, getTextPositionSelector, validateSvgMarkup } from '@semiont/core';
2
2
 
3
3
  // src/utils/annotations.ts
4
4
  function getBodySource(body) {
@@ -8,7 +8,7 @@ function getBodySource(body) {
8
8
  const itemType = item.type;
9
9
  const itemSource = item.source;
10
10
  if (itemType === "SpecificResource" && typeof itemSource === "string") {
11
- return resourceUri(itemSource);
11
+ return itemSource;
12
12
  }
13
13
  }
14
14
  }
@@ -18,7 +18,7 @@ function getBodySource(body) {
18
18
  const bodyType = body.type;
19
19
  const bodySource = body.source;
20
20
  if (bodyType === "SpecificResource" && typeof bodySource === "string") {
21
- return resourceUri(bodySource);
21
+ return bodySource;
22
22
  }
23
23
  }
24
24
  return null;
@@ -49,9 +49,9 @@ function isBodyResolved(body) {
49
49
  }
50
50
  function getTargetSource(target) {
51
51
  if (typeof target === "string") {
52
- return resourceUri(target);
52
+ return target;
53
53
  }
54
- return resourceUri(target.source);
54
+ return target.source;
55
55
  }
56
56
  function getTargetSelector(target) {
57
57
  if (typeof target === "string") {
@@ -119,49 +119,12 @@ function getPrimarySelector(selector) {
119
119
  }
120
120
  return selector;
121
121
  }
122
- function getTextPositionSelector(selector) {
123
- if (!selector) return null;
124
- const selectors = Array.isArray(selector) ? selector : [selector];
125
- const found = selectors.find((s) => s.type === "TextPositionSelector");
126
- if (!found) return null;
127
- return found.type === "TextPositionSelector" ? found : null;
128
- }
129
122
  function getTextQuoteSelector(selector) {
130
123
  const selectors = Array.isArray(selector) ? selector : [selector];
131
124
  const found = selectors.find((s) => s.type === "TextQuoteSelector");
132
125
  if (!found) return null;
133
126
  return found.type === "TextQuoteSelector" ? found : null;
134
127
  }
135
- function getSvgSelector(selector) {
136
- if (!selector) return null;
137
- const selectors = Array.isArray(selector) ? selector : [selector];
138
- const found = selectors.find((s) => s.type === "SvgSelector");
139
- if (!found) return null;
140
- return found.type === "SvgSelector" ? found : null;
141
- }
142
- function getFragmentSelector(selector) {
143
- if (!selector) return null;
144
- const selectors = Array.isArray(selector) ? selector : [selector];
145
- const found = selectors.find((s) => s.type === "FragmentSelector");
146
- if (!found) return null;
147
- return found.type === "FragmentSelector" ? found : null;
148
- }
149
- function validateSvgMarkup(svg) {
150
- if (!svg.includes('xmlns="http://www.w3.org/2000/svg"')) {
151
- return 'SVG must include xmlns="http://www.w3.org/2000/svg" attribute';
152
- }
153
- if (!svg.includes("<svg") || !svg.includes("</svg>")) {
154
- return "SVG must have opening and closing tags";
155
- }
156
- const shapeElements = ["rect", "circle", "ellipse", "polygon", "polyline", "path", "line"];
157
- const hasShape = shapeElements.some(
158
- (shape) => svg.includes(`<${shape}`) || svg.includes(`<${shape} `)
159
- );
160
- if (!hasShape) {
161
- return "SVG must contain at least one shape element (rect, circle, ellipse, polygon, polyline, path, or line)";
162
- }
163
- return null;
164
- }
165
128
  function extractBoundingBox(svg) {
166
129
  const viewBoxMatch = svg.match(/<svg[^>]*viewBox="([^"]+)"/);
167
130
  if (viewBoxMatch) {
@@ -395,13 +358,7 @@ function getAllLocaleCodes() {
395
358
  // src/utils/resources.ts
396
359
  function getResourceId(resource) {
397
360
  if (!resource) return void 0;
398
- const fullId = resource["@id"];
399
- if (fullId.includes("/resources/")) {
400
- const parts = fullId.split("/resources/");
401
- const lastPart = parts[parts.length - 1];
402
- return lastPart || void 0;
403
- }
404
- return void 0;
361
+ return resource["@id"] || void 0;
405
362
  }
406
363
  function getPrimaryRepresentation(resource) {
407
364
  if (!resource?.representations) return void 0;
@@ -684,6 +641,6 @@ function isValidEmail(email) {
684
641
  return emailRegex.test(email);
685
642
  }
686
643
 
687
- export { JWTTokenSchema, LOCALES, buildContentCache, createCircleSvg, createPolygonSvg, createRectangleSvg, decodeRepresentation, decodeWithCharset, extractBoundingBox, extractCharset, extractContext, findBestTextMatch, findTextWithContext, formatLocaleDisplay, getAllLocaleCodes, getAnnotationExactText, getBodySource, getBodyType, getChecksum, getCommentText, getCreator, getDerivedFrom, getExactText, getFragmentSelector, getLanguage, getLocaleEnglishName, getLocaleInfo, getLocaleNativeName, getNodeEncoding, getPrimaryMediaType, getPrimaryRepresentation, getPrimarySelector, getResourceEntityTypes, getResourceId, getStorageUri, getSvgSelector, getTargetSelector, getTargetSource, getTextPositionSelector, getTextQuoteSelector, hasTargetSelector, isArchived, isAssessment, isBodyResolved, isComment, isDraft, isHighlight, isReference, isResolvedReference, isStubReference, isTag, isValidEmail, normalizeCoordinates, normalizeText, parseSvgSelector, scaleSvgToNative, validateAndCorrectOffsets, validateData, validateSvgMarkup, verifyPosition };
644
+ export { JWTTokenSchema, LOCALES, buildContentCache, createCircleSvg, createPolygonSvg, createRectangleSvg, decodeRepresentation, decodeWithCharset, extractBoundingBox, extractCharset, extractContext, findBestTextMatch, findTextWithContext, formatLocaleDisplay, getAllLocaleCodes, getAnnotationExactText, getBodySource, getBodyType, getChecksum, getCommentText, getCreator, getDerivedFrom, getExactText, getLanguage, getLocaleEnglishName, getLocaleInfo, getLocaleNativeName, getNodeEncoding, getPrimaryMediaType, getPrimaryRepresentation, getPrimarySelector, getResourceEntityTypes, getResourceId, getStorageUri, getTargetSelector, getTargetSource, getTextQuoteSelector, hasTargetSelector, isArchived, isAssessment, isBodyResolved, isComment, isDraft, isHighlight, isReference, isResolvedReference, isStubReference, isTag, isValidEmail, normalizeCoordinates, normalizeText, parseSvgSelector, scaleSvgToNative, validateAndCorrectOffsets, validateData, verifyPosition };
688
645
  //# sourceMappingURL=index.js.map
689
646
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/annotations.ts","../../src/utils/fuzzy-anchor.ts","../../src/utils/locales.ts","../../src/utils/resources.ts","../../src/utils/svg-utils.ts","../../src/utils/text-context.ts","../../src/utils/text-encoding.ts","../../src/utils/validation.ts"],"names":["pos","context"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Annotation and Selector Utilities\n *\n * Pure TypeScript utilities for working with W3C Web Annotations.\n * No React dependencies - safe to use in any JavaScript environment.\n *\n * Body is either empty array (stub) or single SpecificResource (resolved)\n * Body can be array of TextualBody (tagging) + SpecificResource (linking)\n * Target can be simple string IRI or object with source and optional selector\n */\n\nimport type { components } from '@semiont/core';\nimport type { ResourceUri } from '@semiont/core';\nimport { resourceUri } from '@semiont/core';\n\ntype Annotation = components['schemas']['Annotation'];\ntype HighlightAnnotation = Annotation;\ntype ReferenceAnnotation = Annotation;\ntype TextPositionSelector = components['schemas']['TextPositionSelector'];\ntype TextQuoteSelector = components['schemas']['TextQuoteSelector'];\ntype SvgSelector = components['schemas']['SvgSelector'];\ntype FragmentSelector = components['schemas']['FragmentSelector'];\ntype Selector = TextPositionSelector | TextQuoteSelector | SvgSelector | FragmentSelector;\n\n// Re-export selector types for convenience\nexport type { TextPositionSelector, TextQuoteSelector, SvgSelector, FragmentSelector, Selector };\n\n/**\n * Get the source from an annotation body (null if stub)\n * Search for SpecificResource in body array\n */\nexport function getBodySource(body: Annotation['body']): ResourceUri | null {\n if (Array.isArray(body)) {\n // Search for SpecificResource with source\n for (const item of body) {\n if (\n typeof item === 'object' &&\n item !== null &&\n 'type' in item &&\n 'source' in item\n ) {\n const itemType = (item as { type: unknown }).type;\n const itemSource = (item as { source: unknown }).source;\n\n if (itemType === 'SpecificResource' && typeof itemSource === 'string') {\n return resourceUri(itemSource);\n }\n }\n }\n return null; // No SpecificResource found = stub\n }\n\n // Single body object (SpecificResource)\n if (\n typeof body === 'object' &&\n body !== null &&\n 'type' in body &&\n 'source' in body\n ) {\n const bodyType = (body as { type: unknown }).type;\n const bodySource = (body as { source: unknown }).source;\n\n if (bodyType === 'SpecificResource' && typeof bodySource === 'string') {\n return resourceUri(bodySource);\n }\n }\n\n return null;\n}\n\n/**\n * Get the type from an annotation body (returns first body type in array)\n */\nexport function getBodyType(body: Annotation['body']): 'TextualBody' | 'SpecificResource' | null {\n if (Array.isArray(body)) {\n if (body.length === 0) {\n return null;\n }\n // Return type of first body item\n if (typeof body[0] === 'object' && body[0] !== null && 'type' in body[0]) {\n const firstType = (body[0] as { type: unknown }).type;\n if (firstType === 'TextualBody' || firstType === 'SpecificResource') {\n return firstType;\n }\n }\n return null;\n }\n\n // Single body object\n if (typeof body === 'object' && body !== null && 'type' in body) {\n const bodyType = (body as { type: unknown }).type;\n if (bodyType === 'TextualBody' || bodyType === 'SpecificResource') {\n return bodyType;\n }\n }\n\n return null;\n}\n\n/**\n * Check if body is resolved (has a source)\n * Check for SpecificResource in body array\n */\nexport function isBodyResolved(body: Annotation['body']): boolean {\n return getBodySource(body) !== null;\n}\n\n/**\n * Get the source IRI from target (handles both string and object forms)\n */\nexport function getTargetSource(target: Annotation['target']): ResourceUri {\n if (typeof target === 'string') {\n return resourceUri(target);\n }\n return resourceUri(target.source);\n}\n\n/**\n * Get the selector from target (undefined if string or no selector)\n */\nexport function getTargetSelector(target: Annotation['target']) {\n if (typeof target === 'string') {\n return undefined;\n }\n return target.selector;\n}\n\n/**\n * Check if target has a selector\n */\nexport function hasTargetSelector(target: Annotation['target']): boolean {\n return typeof target !== 'string' && target.selector !== undefined;\n}\n\n/**\n * Type guard to check if an annotation is a highlight\n */\nexport function isHighlight(annotation: Annotation): annotation is HighlightAnnotation {\n return annotation.motivation === 'highlighting';\n}\n\n/**\n * Type guard to check if an annotation is a reference (linking)\n */\nexport function isReference(annotation: Annotation): annotation is ReferenceAnnotation {\n return annotation.motivation === 'linking';\n}\n\n/**\n * Type guard to check if an annotation is an assessment\n */\nexport function isAssessment(annotation: Annotation): annotation is Annotation {\n return annotation.motivation === 'assessing';\n}\n\n/**\n * Type guard to check if an annotation is a comment\n */\nexport function isComment(annotation: Annotation): annotation is Annotation {\n return annotation.motivation === 'commenting';\n}\n\n/**\n * Type guard to check if an annotation is a tag\n */\nexport function isTag(annotation: Annotation): annotation is Annotation {\n return annotation.motivation === 'tagging';\n}\n\n/**\n * Extract comment text from a comment annotation's body\n * @param annotation - The annotation to extract comment text from\n * @returns The comment text, or undefined if not a comment or no text found\n */\nexport function getCommentText(annotation: Annotation): string | undefined {\n if (!isComment(annotation)) return undefined;\n const body = Array.isArray(annotation.body) ? annotation.body[0] : annotation.body;\n if (body && 'value' in body) {\n return body.value;\n }\n return undefined;\n}\n\n/**\n * Type guard to check if a reference annotation is a stub (unresolved)\n * Stub if no SpecificResource in body array\n */\nexport function isStubReference(annotation: Annotation): boolean {\n return isReference(annotation) && !isBodyResolved(annotation.body);\n}\n\n/**\n * Type guard to check if a reference annotation is resolved\n * Resolved if SpecificResource exists in body array\n */\nexport function isResolvedReference(annotation: Annotation): annotation is ReferenceAnnotation {\n return isReference(annotation) && isBodyResolved(annotation.body);\n}\n\n// =============================================================================\n// SELECTOR UTILITIES\n// =============================================================================\n\n/**\n * Get the exact text from a selector (single or array)\n *\n * When selector is an array, tries to find a TextQuoteSelector (which has exact text).\n * TextPositionSelector does not have exact text, only character offsets.\n * Handles undefined selector (when target is a string IRI with no selector)\n */\nexport function getExactText(selector: Selector | Selector[] | undefined): string {\n if (!selector) {\n return ''; // No selector means entire resource\n }\n const selectors = Array.isArray(selector) ? selector : [selector];\n\n // Try to find TextQuoteSelector (has exact text)\n const quoteSelector = selectors.find(s => s.type === 'TextQuoteSelector') as TextQuoteSelector | undefined;\n if (quoteSelector) {\n return quoteSelector.exact;\n }\n\n // No TextQuoteSelector found\n return '';\n}\n\n/**\n * Get the exact text from an annotation's target selector\n * Uses getTargetSelector helper to safely get selector\n */\nexport function getAnnotationExactText(annotation: Annotation): string {\n const selector = getTargetSelector(annotation.target);\n return getExactText(selector as Selector | Selector[] | undefined);\n}\n\n/**\n * Get the primary selector from a selector (single or array)\n *\n * When selector is an array, returns the first selector.\n * When selector is a single object, returns it as-is.\n */\nexport function getPrimarySelector(selector: Selector | Selector[]): Selector {\n if (Array.isArray(selector)) {\n if (selector.length === 0) {\n throw new Error('Empty selector array');\n }\n const first = selector[0];\n if (!first) {\n throw new Error('Invalid selector array');\n }\n return first;\n }\n return selector;\n}\n\n/**\n * Get TextPositionSelector from a selector (single or array)\n *\n * Returns the first TextPositionSelector found, or null if none exists.\n * Handles undefined selector (when target is a string IRI with no selector)\n */\nexport function getTextPositionSelector(selector: Selector | Selector[] | undefined): TextPositionSelector | null {\n if (!selector) return null; // No selector means entire resource\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'TextPositionSelector');\n if (!found) return null;\n return found.type === 'TextPositionSelector' ? found : null;\n}\n\n/**\n * Get TextQuoteSelector from a selector (single or array)\n *\n * Returns the first TextQuoteSelector found, or null if none exists.\n */\nexport function getTextQuoteSelector(selector: Selector | Selector[]): TextQuoteSelector | null {\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'TextQuoteSelector');\n if (!found) return null;\n return found.type === 'TextQuoteSelector' ? found : null;\n}\n\n/**\n * Get SvgSelector from a selector (single or array)\n *\n * Returns the first SvgSelector found, or null if none exists.\n */\nexport function getSvgSelector(selector: Selector | Selector[] | undefined): SvgSelector | null {\n if (!selector) return null;\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'SvgSelector');\n if (!found) return null;\n return found.type === 'SvgSelector' ? found : null;\n}\n\n/**\n * Get FragmentSelector from a selector (single or array)\n *\n * Returns the first FragmentSelector found, or null if none exists.\n */\nexport function getFragmentSelector(selector: Selector | Selector[] | undefined): FragmentSelector | null {\n if (!selector) return null;\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'FragmentSelector');\n if (!found) return null;\n return found.type === 'FragmentSelector' ? found : null;\n}\n\n/**\n * Validate SVG markup for W3C compliance\n *\n * Checks that:\n * - SVG contains xmlns attribute\n * - SVG is well-formed XML\n * - SVG contains at least one shape element\n *\n * @returns null if valid, error message if invalid\n */\nexport function validateSvgMarkup(svg: string): string | null {\n // Check for xmlns attribute (required by W3C spec)\n if (!svg.includes('xmlns=\"http://www.w3.org/2000/svg\"')) {\n return 'SVG must include xmlns=\"http://www.w3.org/2000/svg\" attribute';\n }\n\n // Check for basic SVG tag structure\n if (!svg.includes('<svg') || !svg.includes('</svg>')) {\n return 'SVG must have opening and closing tags';\n }\n\n // Check for at least one shape element\n const shapeElements = ['rect', 'circle', 'ellipse', 'polygon', 'polyline', 'path', 'line'];\n const hasShape = shapeElements.some(shape =>\n svg.includes(`<${shape}`) || svg.includes(`<${shape} `)\n );\n\n if (!hasShape) {\n return 'SVG must contain at least one shape element (rect, circle, ellipse, polygon, polyline, path, or line)';\n }\n\n return null; // Valid\n}\n\n/**\n * Extract bounding box from SVG markup\n *\n * Attempts to extract x, y, width, height from the SVG viewBox or root element.\n * Returns null if bounding box cannot be determined.\n */\nexport function extractBoundingBox(svg: string): { x: number; y: number; width: number; height: number } | null {\n // Try to extract viewBox attribute from SVG element\n const viewBoxMatch = svg.match(/<svg[^>]*viewBox=\"([^\"]+)\"/);\n if (viewBoxMatch) {\n const values = viewBoxMatch[1].split(/\\s+/).map(parseFloat);\n if (values.length === 4 && values.every(v => !isNaN(v))) {\n return {\n x: values[0],\n y: values[1],\n width: values[2],\n height: values[3]\n };\n }\n }\n\n // Try to extract width/height attributes from SVG element (assume x=0, y=0)\n const svgTagMatch = svg.match(/<svg[^>]*>/);\n if (svgTagMatch) {\n const svgTag = svgTagMatch[0];\n const widthMatch = svgTag.match(/width=\"([^\"]+)\"/);\n const heightMatch = svgTag.match(/height=\"([^\"]+)\"/);\n\n if (widthMatch && heightMatch) {\n const width = parseFloat(widthMatch[1]);\n const height = parseFloat(heightMatch[1]);\n\n if (!isNaN(width) && !isNaN(height)) {\n return { x: 0, y: 0, width, height };\n }\n }\n }\n\n return null;\n}\n","/**\n * Fuzzy Anchoring for W3C Web Annotation TextQuoteSelector\n *\n * Uses prefix/suffix context to disambiguate when the same text appears multiple times.\n * Implements fuzzy matching as specified in the W3C Web Annotation Data Model.\n *\n * @see https://www.w3.org/TR/annotation-model/#text-quote-selector\n */\n\nexport interface TextPosition {\n start: number;\n end: number;\n}\n\nexport type MatchQuality = 'exact' | 'normalized' | 'case-insensitive' | 'fuzzy';\n\n/**\n * Normalize text for comparison - handles common document editing changes\n *\n * Collapses whitespace, converts curly quotes to straight quotes,\n * and normalizes common punctuation variations.\n */\nexport function normalizeText(text: string): string {\n return text\n .replace(/\\s+/g, ' ') // collapse whitespace\n .replace(/[\\u2018\\u2019]/g, \"'\") // curly single quotes → straight\n .replace(/[\\u201C\\u201D]/g, '\"') // curly double quotes → straight\n .replace(/\\u2014/g, '--') // em-dash → double hyphen\n .replace(/\\u2013/g, '-') // en-dash → hyphen\n .trim();\n}\n\n/**\n * Calculate Levenshtein distance between two strings\n * Used for fuzzy matching when exact text doesn't match\n */\nfunction levenshteinDistance(str1: string, str2: string): number {\n const len1 = str1.length;\n const len2 = str2.length;\n const matrix: number[][] = [];\n\n // Initialize matrix\n for (let i = 0; i <= len1; i++) {\n matrix[i] = [i];\n }\n for (let j = 0; j <= len2; j++) {\n matrix[0]![j] = j;\n }\n\n // Fill matrix\n for (let i = 1; i <= len1; i++) {\n for (let j = 1; j <= len2; j++) {\n const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;\n const deletion = matrix[i - 1]![j]! + 1;\n const insertion = matrix[i]![j - 1]! + 1;\n const substitution = matrix[i - 1]![j - 1]! + cost;\n matrix[i]![j] = Math.min(deletion, insertion, substitution);\n }\n }\n\n return matrix[len1]![len2]!;\n}\n\n/**\n * Pre-computed content strings for batch fuzzy matching.\n * Avoids recomputing normalizeText(content) and content.toLowerCase()\n * for every annotation when processing many annotations against the same content.\n */\nexport interface ContentCache {\n normalizedContent: string;\n lowerContent: string;\n}\n\n/**\n * Build a ContentCache for a given content string.\n * Call once per content, pass to findBestTextMatch/findTextWithContext for all annotations.\n */\nexport function buildContentCache(content: string): ContentCache {\n return {\n normalizedContent: normalizeText(content),\n lowerContent: content.toLowerCase()\n };\n}\n\n/**\n * Find best match for text in content using multi-strategy search\n *\n * Shared core logic used by both findTextWithContext and validateAndCorrectOffsets.\n *\n * @param content - Full text content to search within\n * @param searchText - The text to find\n * @param positionHint - Hint for where to search (TextPositionSelector.start)\n * @param cache - Pre-computed normalized/lowered content (from buildContentCache)\n * @returns Match with position and quality, or null if not found\n */\nexport function findBestTextMatch(\n content: string,\n searchText: string,\n positionHint: number | undefined,\n cache: ContentCache\n): { start: number; end: number; matchQuality: MatchQuality } | null {\n const maxFuzzyDistance = Math.max(5, Math.floor(searchText.length * 0.05)); // 5% tolerance or min 5 chars\n\n // Strategy 1: Exact match (case-sensitive, exact whitespace)\n const exactIndex = content.indexOf(searchText);\n if (exactIndex !== -1) {\n return {\n start: exactIndex,\n end: exactIndex + searchText.length,\n matchQuality: 'exact'\n };\n }\n\n // Strategy 2: Normalized match (handles whitespace/quote variations)\n const normalizedSearch = normalizeText(searchText);\n const normalizedIndex = cache.normalizedContent.indexOf(normalizedSearch);\n if (normalizedIndex !== -1) {\n // Find actual position in original content by counting characters\n let actualPos = 0;\n let normalizedPos = 0;\n while (normalizedPos < normalizedIndex && actualPos < content.length) {\n const char = content[actualPos]!;\n const normalizedChar = normalizeText(char);\n if (normalizedChar) {\n normalizedPos += normalizedChar.length;\n }\n actualPos++;\n }\n return {\n start: actualPos,\n end: actualPos + searchText.length,\n matchQuality: 'normalized'\n };\n }\n\n // Strategy 3: Case-insensitive match\n const lowerSearch = searchText.toLowerCase();\n const caseInsensitiveIndex = cache.lowerContent.indexOf(lowerSearch);\n if (caseInsensitiveIndex !== -1) {\n return {\n start: caseInsensitiveIndex,\n end: caseInsensitiveIndex + searchText.length,\n matchQuality: 'case-insensitive'\n };\n }\n\n // Strategy 4: Fuzzy match using Levenshtein distance with sliding window\n // Search near position hint if provided, otherwise search full content\n const windowSize = searchText.length;\n const searchRadius = Math.min(500, content.length);\n const searchStart = positionHint !== undefined\n ? Math.max(0, positionHint - searchRadius)\n : 0;\n const searchEnd = positionHint !== undefined\n ? Math.min(content.length, positionHint + searchRadius)\n : content.length;\n\n let bestMatch: { start: number; distance: number } | null = null;\n\n // Scan through content with sliding window\n for (let i = searchStart; i <= searchEnd - windowSize; i++) {\n const candidate = content.substring(i, i + windowSize);\n const distance = levenshteinDistance(searchText, candidate);\n\n if (distance <= maxFuzzyDistance) {\n if (!bestMatch || distance < bestMatch.distance) {\n bestMatch = { start: i, distance };\n }\n }\n }\n\n if (bestMatch) {\n return {\n start: bestMatch.start,\n end: bestMatch.start + windowSize,\n matchQuality: 'fuzzy'\n };\n }\n\n return null;\n}\n\n/**\n * Find text using exact match with optional prefix/suffix context\n *\n * When the exact text appears multiple times in the content, prefix and suffix\n * are used to disambiguate and find the correct occurrence.\n *\n * If exact text is not found, uses multi-strategy fuzzy matching (normalization,\n * case-insensitive, Levenshtein distance) to locate changed text.\n *\n * @param content - Full text content to search within\n * @param exact - The exact text to find\n * @param prefix - Optional text that should appear immediately before the match\n * @param suffix - Optional text that should appear immediately after the match\n * @param positionHint - Optional position hint (from TextPositionSelector) for fuzzy search\n * @returns Position of the matched text, or null if not found\n *\n * @example\n * ```typescript\n * const content = \"The cat sat. The cat ran.\";\n * // Find second \"The cat\" occurrence\n * const pos = findTextWithContext(content, \"The cat\", \"sat. \", \" ran\");\n * // Returns { start: 13, end: 20 }\n * ```\n */\nexport function findTextWithContext(\n content: string,\n exact: string,\n prefix: string | undefined,\n suffix: string | undefined,\n positionHint: number | undefined,\n cache: ContentCache\n): TextPosition | null {\n if (!exact) return null;\n\n // Fast path: if positionHint points directly at the exact text, return immediately\n if (positionHint !== undefined && positionHint >= 0 && positionHint + exact.length <= content.length) {\n if (content.substring(positionHint, positionHint + exact.length) === exact) {\n return { start: positionHint, end: positionHint + exact.length };\n }\n }\n\n // Find all occurrences of exact text\n const occurrences: number[] = [];\n let index = content.indexOf(exact);\n while (index !== -1) {\n occurrences.push(index);\n index = content.indexOf(exact, index + 1);\n }\n\n // No exact matches found - try fuzzy matching\n if (occurrences.length === 0) {\n const fuzzyMatch = findBestTextMatch(content, exact, positionHint, cache);\n\n if (fuzzyMatch) {\n return { start: fuzzyMatch.start, end: fuzzyMatch.end };\n }\n\n return null;\n }\n\n // Only one match - no need for prefix/suffix disambiguation\n if (occurrences.length === 1) {\n const pos = occurrences[0]!; // Safe: length === 1 means first element exists\n return { start: pos, end: pos + exact.length };\n }\n\n // Multiple matches - use prefix/suffix to disambiguate\n if (prefix || suffix) {\n for (const pos of occurrences) {\n // Extract actual prefix from content\n const actualPrefixStart = Math.max(0, pos - (prefix?.length || 0));\n const actualPrefix = content.substring(actualPrefixStart, pos);\n\n // Extract actual suffix from content\n const actualSuffixEnd = Math.min(content.length, pos + exact.length + (suffix?.length || 0));\n const actualSuffix = content.substring(pos + exact.length, actualSuffixEnd);\n\n // Check if prefix matches\n const prefixMatch = !prefix || actualPrefix.endsWith(prefix);\n\n // Check if suffix matches\n const suffixMatch = !suffix || actualSuffix.startsWith(suffix);\n\n if (prefixMatch && suffixMatch) {\n return { start: pos, end: pos + exact.length };\n }\n }\n\n // No match with exact prefix/suffix - try partial prefix/suffix match\n for (const pos of occurrences) {\n const actualPrefix = content.substring(Math.max(0, pos - (prefix?.length || 0)), pos);\n const actualSuffix = content.substring(pos + exact.length, pos + exact.length + (suffix?.length || 0));\n\n // Fuzzy match: check if prefix/suffix are substrings (handles whitespace variations)\n const fuzzyPrefixMatch = !prefix || actualPrefix.includes(prefix.trim());\n const fuzzySuffixMatch = !suffix || actualSuffix.includes(suffix.trim());\n\n if (fuzzyPrefixMatch && fuzzySuffixMatch) {\n return { start: pos, end: pos + exact.length };\n }\n }\n }\n\n // Fallback: return first occurrence if no prefix/suffix or no match\n const pos = occurrences[0]!; // Safe: we checked length > 0 earlier\n return { start: pos, end: pos + exact.length };\n}\n\n/**\n * Verify that a position correctly points to the exact text\n * Useful for debugging and validation\n */\nexport function verifyPosition(\n content: string,\n position: TextPosition,\n expectedExact: string\n): boolean {\n const actualText = content.substring(position.start, position.end);\n return actualText === expectedExact;\n}\n","/**\n * Locale information\n * Copied from SDK for frontend use\n */\n\nexport interface LocaleInfo {\n code: string;\n nativeName: string;\n englishName: string;\n}\n\nexport const LOCALES: readonly LocaleInfo[] = [\n { code: 'ar', nativeName: 'العربية', englishName: 'Arabic' },\n { code: 'bn', nativeName: 'বাংলা', englishName: 'Bengali' },\n { code: 'cs', nativeName: 'Čeština', englishName: 'Czech' },\n { code: 'da', nativeName: 'Dansk', englishName: 'Danish' },\n { code: 'de', nativeName: 'Deutsch', englishName: 'German' },\n { code: 'el', nativeName: 'Ελληνικά', englishName: 'Greek' },\n { code: 'en', nativeName: 'English', englishName: 'English' },\n { code: 'es', nativeName: 'Español', englishName: 'Spanish' },\n { code: 'fa', nativeName: 'فارسی', englishName: 'Persian' },\n { code: 'fi', nativeName: 'Suomi', englishName: 'Finnish' },\n { code: 'fr', nativeName: 'Français', englishName: 'French' },\n { code: 'he', nativeName: 'עברית', englishName: 'Hebrew' },\n { code: 'hi', nativeName: 'हिन्दी', englishName: 'Hindi' },\n { code: 'id', nativeName: 'Bahasa Indonesia', englishName: 'Indonesian' },\n { code: 'it', nativeName: 'Italiano', englishName: 'Italian' },\n { code: 'ja', nativeName: '日本語', englishName: 'Japanese' },\n { code: 'ko', nativeName: '한국어', englishName: 'Korean' },\n { code: 'ms', nativeName: 'Bahasa Melayu', englishName: 'Malay' },\n { code: 'nl', nativeName: 'Nederlands', englishName: 'Dutch' },\n { code: 'no', nativeName: 'Norsk', englishName: 'Norwegian' },\n { code: 'pl', nativeName: 'Polski', englishName: 'Polish' },\n { code: 'pt', nativeName: 'Português', englishName: 'Portuguese' },\n { code: 'ro', nativeName: 'Română', englishName: 'Romanian' },\n { code: 'sv', nativeName: 'Svenska', englishName: 'Swedish' },\n { code: 'th', nativeName: 'ไทย', englishName: 'Thai' },\n { code: 'tr', nativeName: 'Türkçe', englishName: 'Turkish' },\n { code: 'uk', nativeName: 'Українська', englishName: 'Ukrainian' },\n { code: 'vi', nativeName: 'Tiếng Việt', englishName: 'Vietnamese' },\n { code: 'zh', nativeName: '中文', englishName: 'Chinese' },\n] as const;\n\n// Create lookup map for efficient access\nconst localeByCode = new Map<string, LocaleInfo>(\n LOCALES.map(locale => [locale.code.toLowerCase(), locale])\n);\n\n/**\n * Get locale information by code\n */\nexport function getLocaleInfo(code: string | undefined): LocaleInfo | undefined {\n if (!code) return undefined;\n return localeByCode.get(code.toLowerCase());\n}\n\n/**\n * Get the native name of a language by its locale code\n */\nexport function getLocaleNativeName(code: string | undefined): string | undefined {\n return getLocaleInfo(code)?.nativeName;\n}\n\n/**\n * Get the English name of a language by its locale code\n */\nexport function getLocaleEnglishName(code: string | undefined): string | undefined {\n return getLocaleInfo(code)?.englishName;\n}\n\n/**\n * Format locale code for display as \"Native Name (code)\"\n */\nexport function formatLocaleDisplay(code: string | undefined): string | undefined {\n if (!code) return undefined;\n\n const info = getLocaleInfo(code);\n if (!info) return code;\n\n return `${info.nativeName} (${code.toLowerCase()})`;\n}\n\n/**\n * Get all supported locale codes\n */\nexport function getAllLocaleCodes(): readonly string[] {\n return LOCALES.map(l => l.code);\n}\n","/**\n * Helper functions for working with W3C ResourceDescriptor\n */\n\nimport type { components } from '@semiont/core';\n\ntype ResourceDescriptor = components['schemas']['ResourceDescriptor'];\ntype Representation = components['schemas']['Representation'];\n\n/**\n * Get the resource ID from @id property\n *\n * For internal resources: extracts UUID from \"http://localhost:4000/resources/{uuid}\"\n * For external resources: returns undefined\n *\n * This is used for routing - the frontend URL should contain only the resource ID,\n * not the full HTTP URI.\n */\nexport function getResourceId(resource: ResourceDescriptor | undefined): string | undefined {\n if (!resource) return undefined;\n\n const fullId = resource['@id'];\n\n // For internal resources, extract the last path segment\n // http://localhost:4000/resources/{uuid} -> {uuid}\n if (fullId.includes('/resources/')) {\n const parts = fullId.split('/resources/');\n const lastPart = parts[parts.length - 1];\n return lastPart || undefined;\n }\n\n // For external resources, cannot extract ID\n return undefined;\n}\n\n/**\n * Get the primary representation (first or only representation)\n */\nexport function getPrimaryRepresentation(resource: ResourceDescriptor | undefined): Representation | undefined {\n if (!resource?.representations) return undefined;\n const reps = Array.isArray(resource.representations)\n ? resource.representations\n : [resource.representations];\n return reps[0];\n}\n\n/**\n * Get the media type from the primary representation\n */\nexport function getPrimaryMediaType(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.mediaType;\n}\n\n/**\n * Get the checksum from the primary representation\n */\nexport function getChecksum(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.checksum;\n}\n\n/**\n * Get the language from the primary representation\n */\nexport function getLanguage(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.language;\n}\n\n/**\n * Get storage URI from primary representation\n *\n * @param resource - ResourceDescriptor\n * @returns Storage URI or undefined\n */\nexport function getStorageUri(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.storageUri;\n}\n\n/**\n * Get creator agent from wasAttributedTo\n * Handles both single agent and array of agents\n *\n * @param resource - ResourceDescriptor\n * @returns First agent or undefined\n */\nexport function getCreator(resource: ResourceDescriptor | undefined): components['schemas']['Agent'] | undefined {\n if (!resource?.wasAttributedTo) return undefined;\n\n return Array.isArray(resource.wasAttributedTo)\n ? resource.wasAttributedTo[0]\n : resource.wasAttributedTo;\n}\n\n/**\n * Get derived-from URI\n * Handles both single URI and array of URIs\n *\n * @param resource - ResourceDescriptor\n * @returns First derivation URI or undefined\n */\nexport function getDerivedFrom(resource: ResourceDescriptor | undefined): string | undefined {\n if (!resource?.wasDerivedFrom) return undefined;\n\n return Array.isArray(resource.wasDerivedFrom)\n ? resource.wasDerivedFrom[0]\n : resource.wasDerivedFrom;\n}\n\n/**\n * Check if resource is archived (application-specific field)\n *\n * @param resource - ResourceDescriptor\n * @returns True if archived, false otherwise\n */\nexport function isArchived(resource: ResourceDescriptor | undefined): boolean {\n return resource?.archived === true;\n}\n\n/**\n * Get entity types from resource (application-specific field)\n *\n * @param resource - ResourceDescriptor\n * @returns Array of entity types, empty if not set\n */\nexport function getResourceEntityTypes(resource: ResourceDescriptor | undefined): string[] {\n return resource?.entityTypes || [];\n}\n\n/**\n * Check if resource is a draft (application-specific field)\n *\n * @param resource - ResourceDescriptor\n * @returns True if draft, false otherwise\n */\nexport function isDraft(resource: ResourceDescriptor | undefined): boolean {\n return resource?.isDraft === true;\n}\n\n/**\n * Map charset names to Node.js Buffer encoding names\n * Node.js Buffer.toString() supports: 'utf8', 'utf16le', 'latin1', 'base64', 'hex', 'ascii', 'binary', 'ucs2'\n *\n * @param charset - Charset name (e.g., \"UTF-8\", \"ISO-8859-1\", \"Windows-1252\")\n * @returns Node.js BufferEncoding\n */\nexport function getNodeEncoding(charset: string): BufferEncoding {\n const normalized = charset.toLowerCase().replace(/[-_]/g, '');\n\n // Map common charset names to Node.js encodings\n const charsetMap: Record<string, BufferEncoding> = {\n 'utf8': 'utf8',\n 'iso88591': 'latin1',\n 'latin1': 'latin1',\n 'ascii': 'ascii',\n 'usascii': 'ascii',\n 'utf16le': 'utf16le',\n 'ucs2': 'ucs2',\n 'binary': 'binary',\n 'windows1252': 'latin1', // Windows-1252 is a superset of Latin-1\n 'cp1252': 'latin1',\n };\n\n return charsetMap[normalized] || 'utf8';\n}\n\n/**\n * Decode a representation buffer to string using the correct charset\n * Extracts charset from media type and uses appropriate encoding\n *\n * @param buffer - The raw representation data\n * @param mediaType - Media type with optional charset (e.g., \"text/plain; charset=iso-8859-1\")\n * @returns Decoded string\n *\n * @example\n * ```typescript\n * const content = decodeRepresentation(buffer, \"text/plain; charset=utf-8\");\n * const legacy = decodeRepresentation(buffer, \"text/plain; charset=windows-1252\");\n * ```\n */\nexport function decodeRepresentation(buffer: Buffer, mediaType: string): string {\n // Extract charset from mediaType (e.g., \"text/plain; charset=iso-8859-1\")\n const charsetMatch = mediaType.match(/charset=([^\\s;]+)/i);\n const charset = (charsetMatch?.[1] || 'utf-8').toLowerCase();\n\n // Map to Node.js encoding\n const encoding = getNodeEncoding(charset);\n\n return buffer.toString(encoding);\n}\n","/**\n * SVG Utility Functions\n *\n * Utilities for creating, parsing, and manipulating W3C-compliant SVG selectors\n * for image annotation.\n */\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface BoundingBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Create W3C-compliant SVG rectangle selector\n */\nexport function createRectangleSvg(start: Point, end: Point): string {\n const x = Math.min(start.x, end.x);\n const y = Math.min(start.y, end.y);\n const width = Math.abs(end.x - start.x);\n const height = Math.abs(end.y - start.y);\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"${x}\" y=\"${y}\" width=\"${width}\" height=\"${height}\"/></svg>`;\n}\n\n/**\n * Create W3C-compliant SVG polygon selector\n */\nexport function createPolygonSvg(points: Point[]): string {\n if (points.length < 3) {\n throw new Error('Polygon requires at least 3 points');\n }\n\n const pointsStr = points.map(p => `${p.x},${p.y}`).join(' ');\n return `<svg xmlns=\"http://www.w3.org/2000/svg\"><polygon points=\"${pointsStr}\"/></svg>`;\n}\n\n/**\n * Create W3C-compliant SVG circle selector\n */\nexport function createCircleSvg(center: Point, radius: number): string {\n if (radius <= 0) {\n throw new Error('Circle radius must be positive');\n }\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"${center.x}\" cy=\"${center.y}\" r=\"${radius}\"/></svg>`;\n}\n\n/**\n * Parse SVG selector to extract shape type and data\n */\nexport function parseSvgSelector(svg: string): {\n type: 'rect' | 'polygon' | 'circle' | 'path';\n data: any;\n} | null {\n // Extract rectangle\n const rectMatch = svg.match(/<rect\\s+([^>]+)\\/>/);\n if (rectMatch && rectMatch[1]) {\n const attrs = rectMatch[1];\n const x = parseFloat(attrs.match(/x=\"([^\"]+)\"/)?.[1] || '0');\n const y = parseFloat(attrs.match(/y=\"([^\"]+)\"/)?.[1] || '0');\n const width = parseFloat(attrs.match(/width=\"([^\"]+)\"/)?.[1] || '0');\n const height = parseFloat(attrs.match(/height=\"([^\"]+)\"/)?.[1] || '0');\n\n return {\n type: 'rect',\n data: { x, y, width, height }\n };\n }\n\n // Extract polygon\n const polygonMatch = svg.match(/<polygon\\s+points=\"([^\"]+)\"/);\n if (polygonMatch && polygonMatch[1]) {\n const pointsStr = polygonMatch[1];\n const points = pointsStr.split(/\\s+/).map(pair => {\n const [x, y] = pair.split(',').map(parseFloat);\n return { x, y };\n });\n\n return {\n type: 'polygon',\n data: { points }\n };\n }\n\n // Extract circle\n const circleMatch = svg.match(/<circle\\s+([^>]+)\\/>/);\n if (circleMatch && circleMatch[1]) {\n const attrs = circleMatch[1];\n const cx = parseFloat(attrs.match(/cx=\"([^\"]+)\"/)?.[1] || '0');\n const cy = parseFloat(attrs.match(/cy=\"([^\"]+)\"/)?.[1] || '0');\n const r = parseFloat(attrs.match(/r=\"([^\"]+)\"/)?.[1] || '0');\n\n return {\n type: 'circle',\n data: { cx, cy, r }\n };\n }\n\n return null;\n}\n\n/**\n * Normalize coordinates from display space to image native resolution\n */\nexport function normalizeCoordinates(\n point: Point,\n displayWidth: number,\n displayHeight: number,\n imageWidth: number,\n imageHeight: number\n): Point {\n return {\n x: (point.x / displayWidth) * imageWidth,\n y: (point.y / displayHeight) * imageHeight\n };\n}\n\n/**\n * Scale entire SVG selector from display space to image native resolution\n */\nexport function scaleSvgToNative(\n svg: string,\n displayWidth: number,\n displayHeight: number,\n imageWidth: number,\n imageHeight: number\n): string {\n const parsed = parseSvgSelector(svg);\n if (!parsed) return svg;\n\n const scaleX = imageWidth / displayWidth;\n const scaleY = imageHeight / displayHeight;\n\n switch (parsed.type) {\n case 'rect': {\n const { x, y, width, height } = parsed.data;\n return createRectangleSvg(\n { x: x * scaleX, y: y * scaleY },\n { x: (x + width) * scaleX, y: (y + height) * scaleY }\n );\n }\n\n case 'circle': {\n const { cx, cy, r } = parsed.data;\n return createCircleSvg(\n { x: cx * scaleX, y: cy * scaleY },\n r * Math.min(scaleX, scaleY)\n );\n }\n\n case 'polygon': {\n const points = parsed.data.points.map((p: Point) => ({\n x: p.x * scaleX,\n y: p.y * scaleY\n }));\n return createPolygonSvg(points);\n }\n }\n\n return svg;\n}\n","/**\n * Text context extraction utilities for W3C Web Annotation TextQuoteSelector\n *\n * Provides robust prefix/suffix context extraction with word boundary detection\n * to ensure fuzzy anchoring works correctly when the same text appears multiple times.\n *\n * Also provides AI offset validation and correction for handling AI-generated annotations\n * where the model may return slightly incorrect character offsets.\n *\n * @see https://www.w3.org/TR/annotation-model/#text-quote-selector\n */\n\nimport { findBestTextMatch, buildContentCache, type MatchQuality } from './fuzzy-anchor';\n\n/**\n * Extract prefix and suffix context for TextQuoteSelector\n *\n * Extracts up to 64 characters before and after the selected text,\n * extending to word boundaries to avoid cutting words in half.\n * This ensures prefix/suffix are meaningful context for fuzzy anchoring.\n *\n * @param content - Full text content\n * @param start - Start offset of selection\n * @param end - End offset of selection\n * @returns Object with prefix and suffix (undefined if at boundaries)\n *\n * @example\n * ```typescript\n * const content = \"The United States Congress...\";\n * const context = extractContext(content, 4, 17); // \"United States\"\n * // Returns: { prefix: \"The \", suffix: \" Congress...\" }\n * // NOT: { prefix: \"nited \", suffix: \"gress...\" }\n * ```\n */\nexport function extractContext(\n content: string,\n start: number,\n end: number\n): { prefix?: string; suffix?: string } {\n const CONTEXT_LENGTH = 64;\n const MAX_EXTENSION = 32; // Maximum additional chars to extend for word boundary\n\n // Extract prefix (up to CONTEXT_LENGTH chars before start, extended to word boundary)\n let prefix: string | undefined;\n if (start > 0) {\n let prefixStart = Math.max(0, start - CONTEXT_LENGTH);\n\n // Extend backward to word boundary (whitespace or punctuation)\n // Stop if we hit start of content or exceed MAX_EXTENSION\n let extensionCount = 0;\n while (prefixStart > 0 && extensionCount < MAX_EXTENSION) {\n const char = content[prefixStart - 1];\n // Break on whitespace, punctuation, or common delimiters\n if (!char || /[\\s.,;:!?'\"()\\[\\]{}<>\\/\\\\]/.test(char)) {\n break;\n }\n prefixStart--;\n extensionCount++;\n }\n\n prefix = content.substring(prefixStart, start);\n }\n\n // Extract suffix (up to CONTEXT_LENGTH chars after end, extended to word boundary)\n let suffix: string | undefined;\n if (end < content.length) {\n let suffixEnd = Math.min(content.length, end + CONTEXT_LENGTH);\n\n // Extend forward to word boundary (whitespace or punctuation)\n // Stop if we hit end of content or exceed MAX_EXTENSION\n let extensionCount = 0;\n while (suffixEnd < content.length && extensionCount < MAX_EXTENSION) {\n const char = content[suffixEnd];\n // Break on whitespace, punctuation, or common delimiters\n if (!char || /[\\s.,;:!?'\"()\\[\\]{}<>\\/\\\\]/.test(char)) {\n break;\n }\n suffixEnd++;\n extensionCount++;\n }\n\n suffix = content.substring(end, suffixEnd);\n }\n\n return { prefix, suffix };\n}\n\n/**\n * Result of validating and correcting AI-provided annotation offsets\n */\nexport interface ValidatedAnnotation {\n start: number;\n end: number;\n exact: string;\n prefix?: string;\n suffix?: string;\n corrected: boolean; // True if offsets were adjusted from AI's original values\n fuzzyMatched?: boolean; // True if we had to use fuzzy matching (minor text differences)\n matchQuality?: MatchQuality; // How we found the match\n}\n\n\n/**\n * Validate and correct AI-provided annotation offsets with fuzzy matching tolerance\n *\n * AI models sometimes return offsets that don't match the actual text position,\n * or provide text with minor variations (case differences, whitespace, typos).\n *\n * This function uses a multi-strategy approach:\n * 1. Check if AI's offsets are exactly correct\n * 2. Try exact case-sensitive search\n * 3. Try case-insensitive search\n * 4. Try fuzzy matching with Levenshtein distance (5% tolerance)\n *\n * This ensures we're maximally tolerant of AI errors while still maintaining\n * annotation quality and logging what corrections were made.\n *\n * @param content - Full text content\n * @param aiStart - Start offset from AI\n * @param aiEnd - End offset from AI\n * @param exact - The exact text that should be at this position (from AI)\n * @returns Validated annotation with corrected offsets and context\n * @throws Error if no acceptable match can be found\n *\n * @example\n * ```typescript\n * // AI said start=1143, but actual text is at 1161\n * const result = validateAndCorrectOffsets(\n * content,\n * 1143,\n * 1289,\n * \"the question \\\"whether...\"\n * );\n * // Returns: { start: 1161, end: 1303, exact: \"...\", corrected: true, matchQuality: 'exact', ... }\n * ```\n */\nexport function validateAndCorrectOffsets(\n content: string,\n aiStart: number,\n aiEnd: number,\n exact: string\n): ValidatedAnnotation {\n // First, check if AI's offsets are correct\n const textAtOffset = content.substring(aiStart, aiEnd);\n\n if (textAtOffset === exact) {\n // AI got it right! Just add proper context\n const context = extractContext(content, aiStart, aiEnd);\n return {\n start: aiStart,\n end: aiEnd,\n exact,\n prefix: context.prefix,\n suffix: context.suffix,\n corrected: false,\n matchQuality: 'exact'\n };\n }\n\n // AI's offsets are wrong - try to find the text using multiple strategies\n const cache = buildContentCache(content);\n const match = findBestTextMatch(content, exact, aiStart, cache);\n\n if (!match) {\n throw new Error(\n 'Cannot find acceptable match for text in content. ' +\n 'All search strategies failed. Text may be hallucinated.'\n );\n }\n\n // Found a match! Extract the actual text from content\n const actualText = content.substring(match.start, match.end);\n\n // Extract context using corrected offsets\n const context = extractContext(content, match.start, match.end);\n\n return {\n start: match.start,\n end: match.end,\n exact: actualText, // Use actual text from document, not AI's version\n prefix: context.prefix,\n suffix: context.suffix,\n corrected: true,\n fuzzyMatched: match.matchQuality !== 'exact',\n matchQuality: match.matchQuality\n };\n}\n","/**\n * Text encoding utilities for consistent charset handling\n *\n * Ensures frontend decoding matches backend decoding by respecting\n * charset parameters in mediaType (e.g., \"text/plain; charset=iso-8859-1\")\n */\n\n/**\n * Extract charset from mediaType parameter\n *\n * @param mediaType - Media type with optional charset (e.g., \"text/plain; charset=utf-8\")\n * @returns Charset name in lowercase (defaults to \"utf-8\")\n *\n * @example\n * extractCharset(\"text/plain; charset=iso-8859-1\") // \"iso-8859-1\"\n * extractCharset(\"text/plain\") // \"utf-8\"\n */\nexport function extractCharset(mediaType: string): string {\n const charsetMatch = mediaType.match(/charset=([^\\s;]+)/i);\n return (charsetMatch?.[1] || 'utf-8').toLowerCase();\n}\n\n/**\n * Decode ArrayBuffer to string using charset from mediaType\n *\n * Uses TextDecoder with the charset extracted from mediaType parameter.\n * This ensures the same character space is used for both annotation creation\n * (backend) and rendering (frontend).\n *\n * @param buffer - Binary data to decode\n * @param mediaType - Media type with optional charset parameter\n * @returns Decoded string in the original character space\n *\n * @example\n * const buffer = new Uint8Array([...]);\n * const text = decodeWithCharset(buffer, \"text/plain; charset=iso-8859-1\");\n */\nexport function decodeWithCharset(buffer: ArrayBuffer, mediaType: string): string {\n const charset = extractCharset(mediaType);\n\n // TextDecoder supports standard charset names\n // Common mappings that work in browsers:\n // - utf-8, utf-16, utf-16le, utf-16be\n // - iso-8859-1 through iso-8859-15\n // - windows-1252, windows-1251, etc.\n const decoder = new TextDecoder(charset);\n return decoder.decode(buffer);\n}\n","/**\n * Generic validation utilities for @semiont/api-client\n *\n * Pure TypeScript validation with no external dependencies.\n * Safe to use in any JavaScript environment (Node.js, browser, Deno, etc.)\n */\n\n/**\n * Validation result types\n */\nexport type ValidationSuccess<T> = { success: true; data: T };\nexport type ValidationFailure = { success: false; error: string; details?: string[] };\nexport type ValidationResult<T> = ValidationSuccess<T> | ValidationFailure;\n\n/**\n * JWT Token validation\n *\n * Validates JWT token format (header.payload.signature).\n * Does not verify signature - use for format validation only.\n */\nexport const JWTTokenSchema = {\n parse(token: unknown): string {\n if (typeof token !== 'string') {\n throw new Error('Token must be a string');\n }\n if (!token || token.length === 0) {\n throw new Error('Token is required');\n }\n // JWT format: header.payload.signature\n const jwtRegex = /^[A-Za-z0-9\\-_]+\\.[A-Za-z0-9\\-_]+\\.[A-Za-z0-9\\-_]*$/;\n if (!jwtRegex.test(token)) {\n throw new Error('Invalid JWT token format');\n }\n return token;\n },\n\n safeParse(token: unknown): ValidationResult<string> {\n try {\n const validated = this.parse(token);\n return { success: true, data: validated };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Invalid JWT token',\n };\n }\n },\n};\n\n/**\n * Generic validation helper with error formatting\n *\n * Wraps any schema's parse method with try/catch and returns ValidationResult.\n *\n * @example\n * ```typescript\n * const result = validateData(JWTTokenSchema, 'eyJ...');\n * if (result.success) {\n * console.log('Valid token:', result.data);\n * } else {\n * console.error('Invalid:', result.error);\n * }\n * ```\n */\nexport function validateData<T>(\n schema: { parse(data: unknown): T },\n data: unknown\n): ValidationResult<T> {\n try {\n const validated = schema.parse(data);\n return { success: true, data: validated };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Validation failed',\n };\n }\n}\n\n/**\n * Email validation helper\n *\n * Validates email format using RFC 5322 simplified regex.\n *\n * @param email - Email address to validate\n * @returns true if valid email format\n */\nexport function isValidEmail(email: string): boolean {\n if (email.length < 1 || email.length > 255) {\n return false;\n }\n // RFC 5322 simplified email regex\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(email);\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils/annotations.ts","../../src/utils/fuzzy-anchor.ts","../../src/utils/locales.ts","../../src/utils/resources.ts","../../src/utils/svg-utils.ts","../../src/utils/text-context.ts","../../src/utils/text-encoding.ts","../../src/utils/validation.ts"],"names":["pos","context"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Annotation and Selector Utilities\n *\n * Pure TypeScript utilities for working with W3C Web Annotations.\n * No React dependencies - safe to use in any JavaScript environment.\n *\n * Body is either empty array (stub) or single SpecificResource (resolved)\n * Body can be array of TextualBody (tagging) + SpecificResource (linking)\n * Target can be simple string IRI or object with source and optional selector\n */\n\nimport type { components, Selector } from '@semiont/core';\n\n// Re-export selector utilities from core (canonical location)\nexport {\n getTextPositionSelector,\n getSvgSelector,\n getFragmentSelector,\n validateSvgMarkup,\n} from '@semiont/core';\n\ntype Annotation = components['schemas']['Annotation'];\ntype HighlightAnnotation = Annotation;\ntype ReferenceAnnotation = Annotation;\ntype TextPositionSelector = components['schemas']['TextPositionSelector'];\ntype TextQuoteSelector = components['schemas']['TextQuoteSelector'];\ntype SvgSelector = components['schemas']['SvgSelector'];\ntype FragmentSelector = components['schemas']['FragmentSelector'];\n\n// Re-export selector types for convenience\nexport type { TextPositionSelector, TextQuoteSelector, SvgSelector, FragmentSelector, Selector };\n\n/**\n * Get the source from an annotation body (null if stub)\n * Search for SpecificResource in body array\n */\nexport function getBodySource(body: Annotation['body']): string | null {\n if (Array.isArray(body)) {\n // Search for SpecificResource with source\n for (const item of body) {\n if (\n typeof item === 'object' &&\n item !== null &&\n 'type' in item &&\n 'source' in item\n ) {\n const itemType = (item as { type: unknown }).type;\n const itemSource = (item as { source: unknown }).source;\n\n if (itemType === 'SpecificResource' && typeof itemSource === 'string') {\n return itemSource;\n }\n }\n }\n return null; // No SpecificResource found = stub\n }\n\n // Single body object (SpecificResource)\n if (\n typeof body === 'object' &&\n body !== null &&\n 'type' in body &&\n 'source' in body\n ) {\n const bodyType = (body as { type: unknown }).type;\n const bodySource = (body as { source: unknown }).source;\n\n if (bodyType === 'SpecificResource' && typeof bodySource === 'string') {\n return bodySource;\n }\n }\n\n return null;\n}\n\n/**\n * Get the type from an annotation body (returns first body type in array)\n */\nexport function getBodyType(body: Annotation['body']): 'TextualBody' | 'SpecificResource' | null {\n if (Array.isArray(body)) {\n if (body.length === 0) {\n return null;\n }\n // Return type of first body item\n if (typeof body[0] === 'object' && body[0] !== null && 'type' in body[0]) {\n const firstType = (body[0] as { type: unknown }).type;\n if (firstType === 'TextualBody' || firstType === 'SpecificResource') {\n return firstType;\n }\n }\n return null;\n }\n\n // Single body object\n if (typeof body === 'object' && body !== null && 'type' in body) {\n const bodyType = (body as { type: unknown }).type;\n if (bodyType === 'TextualBody' || bodyType === 'SpecificResource') {\n return bodyType;\n }\n }\n\n return null;\n}\n\n/**\n * Check if body is resolved (has a source)\n * Check for SpecificResource in body array\n */\nexport function isBodyResolved(body: Annotation['body']): boolean {\n return getBodySource(body) !== null;\n}\n\n/**\n * Get the source IRI from target (handles both string and object forms)\n */\nexport function getTargetSource(target: Annotation['target']): string {\n if (typeof target === 'string') {\n return target;\n }\n return target.source;\n}\n\n/**\n * Get the selector from target (undefined if string or no selector)\n */\nexport function getTargetSelector(target: Annotation['target']) {\n if (typeof target === 'string') {\n return undefined;\n }\n return target.selector;\n}\n\n/**\n * Check if target has a selector\n */\nexport function hasTargetSelector(target: Annotation['target']): boolean {\n return typeof target !== 'string' && target.selector !== undefined;\n}\n\n/**\n * Type guard to check if an annotation is a highlight\n */\nexport function isHighlight(annotation: Annotation): annotation is HighlightAnnotation {\n return annotation.motivation === 'highlighting';\n}\n\n/**\n * Type guard to check if an annotation is a reference (linking)\n */\nexport function isReference(annotation: Annotation): annotation is ReferenceAnnotation {\n return annotation.motivation === 'linking';\n}\n\n/**\n * Type guard to check if an annotation is an assessment\n */\nexport function isAssessment(annotation: Annotation): annotation is Annotation {\n return annotation.motivation === 'assessing';\n}\n\n/**\n * Type guard to check if an annotation is a comment\n */\nexport function isComment(annotation: Annotation): annotation is Annotation {\n return annotation.motivation === 'commenting';\n}\n\n/**\n * Type guard to check if an annotation is a tag\n */\nexport function isTag(annotation: Annotation): annotation is Annotation {\n return annotation.motivation === 'tagging';\n}\n\n/**\n * Extract comment text from a comment annotation's body\n * @param annotation - The annotation to extract comment text from\n * @returns The comment text, or undefined if not a comment or no text found\n */\nexport function getCommentText(annotation: Annotation): string | undefined {\n if (!isComment(annotation)) return undefined;\n const body = Array.isArray(annotation.body) ? annotation.body[0] : annotation.body;\n if (body && 'value' in body) {\n return body.value;\n }\n return undefined;\n}\n\n/**\n * Type guard to check if a reference annotation is a stub (unresolved)\n * Stub if no SpecificResource in body array\n */\nexport function isStubReference(annotation: Annotation): boolean {\n return isReference(annotation) && !isBodyResolved(annotation.body);\n}\n\n/**\n * Type guard to check if a reference annotation is resolved\n * Resolved if SpecificResource exists in body array\n */\nexport function isResolvedReference(annotation: Annotation): annotation is ReferenceAnnotation {\n return isReference(annotation) && isBodyResolved(annotation.body);\n}\n\n// =============================================================================\n// SELECTOR UTILITIES\n// =============================================================================\n\n/**\n * Get the exact text from a selector (single or array)\n *\n * When selector is an array, tries to find a TextQuoteSelector (which has exact text).\n * TextPositionSelector does not have exact text, only character offsets.\n * Handles undefined selector (when target is a string IRI with no selector)\n */\nexport function getExactText(selector: Selector | Selector[] | undefined): string {\n if (!selector) {\n return ''; // No selector means entire resource\n }\n const selectors = Array.isArray(selector) ? selector : [selector];\n\n // Try to find TextQuoteSelector (has exact text)\n const quoteSelector = selectors.find(s => s.type === 'TextQuoteSelector') as TextQuoteSelector | undefined;\n if (quoteSelector) {\n return quoteSelector.exact;\n }\n\n // No TextQuoteSelector found\n return '';\n}\n\n/**\n * Get the exact text from an annotation's target selector\n * Uses getTargetSelector helper to safely get selector\n */\nexport function getAnnotationExactText(annotation: Annotation): string {\n const selector = getTargetSelector(annotation.target);\n return getExactText(selector as Selector | Selector[] | undefined);\n}\n\n/**\n * Get the primary selector from a selector (single or array)\n *\n * When selector is an array, returns the first selector.\n * When selector is a single object, returns it as-is.\n */\nexport function getPrimarySelector(selector: Selector | Selector[]): Selector {\n if (Array.isArray(selector)) {\n if (selector.length === 0) {\n throw new Error('Empty selector array');\n }\n const first = selector[0];\n if (!first) {\n throw new Error('Invalid selector array');\n }\n return first;\n }\n return selector;\n}\n\n/**\n * Get TextQuoteSelector from a selector (single or array)\n *\n * Returns the first TextQuoteSelector found, or null if none exists.\n */\nexport function getTextQuoteSelector(selector: Selector | Selector[]): TextQuoteSelector | null {\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'TextQuoteSelector');\n if (!found) return null;\n return found.type === 'TextQuoteSelector' ? found : null;\n}\n\n/**\n * Extract bounding box from SVG markup\n *\n * Attempts to extract x, y, width, height from the SVG viewBox or root element.\n * Returns null if bounding box cannot be determined.\n */\nexport function extractBoundingBox(svg: string): { x: number; y: number; width: number; height: number } | null {\n // Try to extract viewBox attribute from SVG element\n const viewBoxMatch = svg.match(/<svg[^>]*viewBox=\"([^\"]+)\"/);\n if (viewBoxMatch) {\n const values = viewBoxMatch[1].split(/\\s+/).map(parseFloat);\n if (values.length === 4 && values.every(v => !isNaN(v))) {\n return {\n x: values[0],\n y: values[1],\n width: values[2],\n height: values[3]\n };\n }\n }\n\n // Try to extract width/height attributes from SVG element (assume x=0, y=0)\n const svgTagMatch = svg.match(/<svg[^>]*>/);\n if (svgTagMatch) {\n const svgTag = svgTagMatch[0];\n const widthMatch = svgTag.match(/width=\"([^\"]+)\"/);\n const heightMatch = svgTag.match(/height=\"([^\"]+)\"/);\n\n if (widthMatch && heightMatch) {\n const width = parseFloat(widthMatch[1]);\n const height = parseFloat(heightMatch[1]);\n\n if (!isNaN(width) && !isNaN(height)) {\n return { x: 0, y: 0, width, height };\n }\n }\n }\n\n return null;\n}\n","/**\n * Fuzzy Anchoring for W3C Web Annotation TextQuoteSelector\n *\n * Uses prefix/suffix context to disambiguate when the same text appears multiple times.\n * Implements fuzzy matching as specified in the W3C Web Annotation Data Model.\n *\n * @see https://www.w3.org/TR/annotation-model/#text-quote-selector\n */\n\nexport interface TextPosition {\n start: number;\n end: number;\n}\n\nexport type MatchQuality = 'exact' | 'normalized' | 'case-insensitive' | 'fuzzy';\n\n/**\n * Normalize text for comparison - handles common document editing changes\n *\n * Collapses whitespace, converts curly quotes to straight quotes,\n * and normalizes common punctuation variations.\n */\nexport function normalizeText(text: string): string {\n return text\n .replace(/\\s+/g, ' ') // collapse whitespace\n .replace(/[\\u2018\\u2019]/g, \"'\") // curly single quotes → straight\n .replace(/[\\u201C\\u201D]/g, '\"') // curly double quotes → straight\n .replace(/\\u2014/g, '--') // em-dash → double hyphen\n .replace(/\\u2013/g, '-') // en-dash → hyphen\n .trim();\n}\n\n/**\n * Calculate Levenshtein distance between two strings\n * Used for fuzzy matching when exact text doesn't match\n */\nfunction levenshteinDistance(str1: string, str2: string): number {\n const len1 = str1.length;\n const len2 = str2.length;\n const matrix: number[][] = [];\n\n // Initialize matrix\n for (let i = 0; i <= len1; i++) {\n matrix[i] = [i];\n }\n for (let j = 0; j <= len2; j++) {\n matrix[0]![j] = j;\n }\n\n // Fill matrix\n for (let i = 1; i <= len1; i++) {\n for (let j = 1; j <= len2; j++) {\n const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;\n const deletion = matrix[i - 1]![j]! + 1;\n const insertion = matrix[i]![j - 1]! + 1;\n const substitution = matrix[i - 1]![j - 1]! + cost;\n matrix[i]![j] = Math.min(deletion, insertion, substitution);\n }\n }\n\n return matrix[len1]![len2]!;\n}\n\n/**\n * Pre-computed content strings for batch fuzzy matching.\n * Avoids recomputing normalizeText(content) and content.toLowerCase()\n * for every annotation when processing many annotations against the same content.\n */\nexport interface ContentCache {\n normalizedContent: string;\n lowerContent: string;\n}\n\n/**\n * Build a ContentCache for a given content string.\n * Call once per content, pass to findBestTextMatch/findTextWithContext for all annotations.\n */\nexport function buildContentCache(content: string): ContentCache {\n return {\n normalizedContent: normalizeText(content),\n lowerContent: content.toLowerCase()\n };\n}\n\n/**\n * Find best match for text in content using multi-strategy search\n *\n * Shared core logic used by both findTextWithContext and validateAndCorrectOffsets.\n *\n * @param content - Full text content to search within\n * @param searchText - The text to find\n * @param positionHint - Hint for where to search (TextPositionSelector.start)\n * @param cache - Pre-computed normalized/lowered content (from buildContentCache)\n * @returns Match with position and quality, or null if not found\n */\nexport function findBestTextMatch(\n content: string,\n searchText: string,\n positionHint: number | undefined,\n cache: ContentCache\n): { start: number; end: number; matchQuality: MatchQuality } | null {\n const maxFuzzyDistance = Math.max(5, Math.floor(searchText.length * 0.05)); // 5% tolerance or min 5 chars\n\n // Strategy 1: Exact match (case-sensitive, exact whitespace)\n const exactIndex = content.indexOf(searchText);\n if (exactIndex !== -1) {\n return {\n start: exactIndex,\n end: exactIndex + searchText.length,\n matchQuality: 'exact'\n };\n }\n\n // Strategy 2: Normalized match (handles whitespace/quote variations)\n const normalizedSearch = normalizeText(searchText);\n const normalizedIndex = cache.normalizedContent.indexOf(normalizedSearch);\n if (normalizedIndex !== -1) {\n // Find actual position in original content by counting characters\n let actualPos = 0;\n let normalizedPos = 0;\n while (normalizedPos < normalizedIndex && actualPos < content.length) {\n const char = content[actualPos]!;\n const normalizedChar = normalizeText(char);\n if (normalizedChar) {\n normalizedPos += normalizedChar.length;\n }\n actualPos++;\n }\n return {\n start: actualPos,\n end: actualPos + searchText.length,\n matchQuality: 'normalized'\n };\n }\n\n // Strategy 3: Case-insensitive match\n const lowerSearch = searchText.toLowerCase();\n const caseInsensitiveIndex = cache.lowerContent.indexOf(lowerSearch);\n if (caseInsensitiveIndex !== -1) {\n return {\n start: caseInsensitiveIndex,\n end: caseInsensitiveIndex + searchText.length,\n matchQuality: 'case-insensitive'\n };\n }\n\n // Strategy 4: Fuzzy match using Levenshtein distance with sliding window\n // Search near position hint if provided, otherwise search full content\n const windowSize = searchText.length;\n const searchRadius = Math.min(500, content.length);\n const searchStart = positionHint !== undefined\n ? Math.max(0, positionHint - searchRadius)\n : 0;\n const searchEnd = positionHint !== undefined\n ? Math.min(content.length, positionHint + searchRadius)\n : content.length;\n\n let bestMatch: { start: number; distance: number } | null = null;\n\n // Scan through content with sliding window\n for (let i = searchStart; i <= searchEnd - windowSize; i++) {\n const candidate = content.substring(i, i + windowSize);\n const distance = levenshteinDistance(searchText, candidate);\n\n if (distance <= maxFuzzyDistance) {\n if (!bestMatch || distance < bestMatch.distance) {\n bestMatch = { start: i, distance };\n }\n }\n }\n\n if (bestMatch) {\n return {\n start: bestMatch.start,\n end: bestMatch.start + windowSize,\n matchQuality: 'fuzzy'\n };\n }\n\n return null;\n}\n\n/**\n * Find text using exact match with optional prefix/suffix context\n *\n * When the exact text appears multiple times in the content, prefix and suffix\n * are used to disambiguate and find the correct occurrence.\n *\n * If exact text is not found, uses multi-strategy fuzzy matching (normalization,\n * case-insensitive, Levenshtein distance) to locate changed text.\n *\n * @param content - Full text content to search within\n * @param exact - The exact text to find\n * @param prefix - Optional text that should appear immediately before the match\n * @param suffix - Optional text that should appear immediately after the match\n * @param positionHint - Optional position hint (from TextPositionSelector) for fuzzy search\n * @returns Position of the matched text, or null if not found\n *\n * @example\n * ```typescript\n * const content = \"The cat sat. The cat ran.\";\n * // Find second \"The cat\" occurrence\n * const pos = findTextWithContext(content, \"The cat\", \"sat. \", \" ran\");\n * // Returns { start: 13, end: 20 }\n * ```\n */\nexport function findTextWithContext(\n content: string,\n exact: string,\n prefix: string | undefined,\n suffix: string | undefined,\n positionHint: number | undefined,\n cache: ContentCache\n): TextPosition | null {\n if (!exact) return null;\n\n // Fast path: if positionHint points directly at the exact text, return immediately\n if (positionHint !== undefined && positionHint >= 0 && positionHint + exact.length <= content.length) {\n if (content.substring(positionHint, positionHint + exact.length) === exact) {\n return { start: positionHint, end: positionHint + exact.length };\n }\n }\n\n // Find all occurrences of exact text\n const occurrences: number[] = [];\n let index = content.indexOf(exact);\n while (index !== -1) {\n occurrences.push(index);\n index = content.indexOf(exact, index + 1);\n }\n\n // No exact matches found - try fuzzy matching\n if (occurrences.length === 0) {\n const fuzzyMatch = findBestTextMatch(content, exact, positionHint, cache);\n\n if (fuzzyMatch) {\n return { start: fuzzyMatch.start, end: fuzzyMatch.end };\n }\n\n return null;\n }\n\n // Only one match - no need for prefix/suffix disambiguation\n if (occurrences.length === 1) {\n const pos = occurrences[0]!; // Safe: length === 1 means first element exists\n return { start: pos, end: pos + exact.length };\n }\n\n // Multiple matches - use prefix/suffix to disambiguate\n if (prefix || suffix) {\n for (const pos of occurrences) {\n // Extract actual prefix from content\n const actualPrefixStart = Math.max(0, pos - (prefix?.length || 0));\n const actualPrefix = content.substring(actualPrefixStart, pos);\n\n // Extract actual suffix from content\n const actualSuffixEnd = Math.min(content.length, pos + exact.length + (suffix?.length || 0));\n const actualSuffix = content.substring(pos + exact.length, actualSuffixEnd);\n\n // Check if prefix matches\n const prefixMatch = !prefix || actualPrefix.endsWith(prefix);\n\n // Check if suffix matches\n const suffixMatch = !suffix || actualSuffix.startsWith(suffix);\n\n if (prefixMatch && suffixMatch) {\n return { start: pos, end: pos + exact.length };\n }\n }\n\n // No match with exact prefix/suffix - try partial prefix/suffix match\n for (const pos of occurrences) {\n const actualPrefix = content.substring(Math.max(0, pos - (prefix?.length || 0)), pos);\n const actualSuffix = content.substring(pos + exact.length, pos + exact.length + (suffix?.length || 0));\n\n // Fuzzy match: check if prefix/suffix are substrings (handles whitespace variations)\n const fuzzyPrefixMatch = !prefix || actualPrefix.includes(prefix.trim());\n const fuzzySuffixMatch = !suffix || actualSuffix.includes(suffix.trim());\n\n if (fuzzyPrefixMatch && fuzzySuffixMatch) {\n return { start: pos, end: pos + exact.length };\n }\n }\n }\n\n // Fallback: return first occurrence if no prefix/suffix or no match\n const pos = occurrences[0]!; // Safe: we checked length > 0 earlier\n return { start: pos, end: pos + exact.length };\n}\n\n/**\n * Verify that a position correctly points to the exact text\n * Useful for debugging and validation\n */\nexport function verifyPosition(\n content: string,\n position: TextPosition,\n expectedExact: string\n): boolean {\n const actualText = content.substring(position.start, position.end);\n return actualText === expectedExact;\n}\n","/**\n * Locale information\n * Copied from SDK for frontend use\n */\n\nexport interface LocaleInfo {\n code: string;\n nativeName: string;\n englishName: string;\n}\n\nexport const LOCALES: readonly LocaleInfo[] = [\n { code: 'ar', nativeName: 'العربية', englishName: 'Arabic' },\n { code: 'bn', nativeName: 'বাংলা', englishName: 'Bengali' },\n { code: 'cs', nativeName: 'Čeština', englishName: 'Czech' },\n { code: 'da', nativeName: 'Dansk', englishName: 'Danish' },\n { code: 'de', nativeName: 'Deutsch', englishName: 'German' },\n { code: 'el', nativeName: 'Ελληνικά', englishName: 'Greek' },\n { code: 'en', nativeName: 'English', englishName: 'English' },\n { code: 'es', nativeName: 'Español', englishName: 'Spanish' },\n { code: 'fa', nativeName: 'فارسی', englishName: 'Persian' },\n { code: 'fi', nativeName: 'Suomi', englishName: 'Finnish' },\n { code: 'fr', nativeName: 'Français', englishName: 'French' },\n { code: 'he', nativeName: 'עברית', englishName: 'Hebrew' },\n { code: 'hi', nativeName: 'हिन्दी', englishName: 'Hindi' },\n { code: 'id', nativeName: 'Bahasa Indonesia', englishName: 'Indonesian' },\n { code: 'it', nativeName: 'Italiano', englishName: 'Italian' },\n { code: 'ja', nativeName: '日本語', englishName: 'Japanese' },\n { code: 'ko', nativeName: '한국어', englishName: 'Korean' },\n { code: 'ms', nativeName: 'Bahasa Melayu', englishName: 'Malay' },\n { code: 'nl', nativeName: 'Nederlands', englishName: 'Dutch' },\n { code: 'no', nativeName: 'Norsk', englishName: 'Norwegian' },\n { code: 'pl', nativeName: 'Polski', englishName: 'Polish' },\n { code: 'pt', nativeName: 'Português', englishName: 'Portuguese' },\n { code: 'ro', nativeName: 'Română', englishName: 'Romanian' },\n { code: 'sv', nativeName: 'Svenska', englishName: 'Swedish' },\n { code: 'th', nativeName: 'ไทย', englishName: 'Thai' },\n { code: 'tr', nativeName: 'Türkçe', englishName: 'Turkish' },\n { code: 'uk', nativeName: 'Українська', englishName: 'Ukrainian' },\n { code: 'vi', nativeName: 'Tiếng Việt', englishName: 'Vietnamese' },\n { code: 'zh', nativeName: '中文', englishName: 'Chinese' },\n] as const;\n\n// Create lookup map for efficient access\nconst localeByCode = new Map<string, LocaleInfo>(\n LOCALES.map(locale => [locale.code.toLowerCase(), locale])\n);\n\n/**\n * Get locale information by code\n */\nexport function getLocaleInfo(code: string | undefined): LocaleInfo | undefined {\n if (!code) return undefined;\n return localeByCode.get(code.toLowerCase());\n}\n\n/**\n * Get the native name of a language by its locale code\n */\nexport function getLocaleNativeName(code: string | undefined): string | undefined {\n return getLocaleInfo(code)?.nativeName;\n}\n\n/**\n * Get the English name of a language by its locale code\n */\nexport function getLocaleEnglishName(code: string | undefined): string | undefined {\n return getLocaleInfo(code)?.englishName;\n}\n\n/**\n * Format locale code for display as \"Native Name (code)\"\n */\nexport function formatLocaleDisplay(code: string | undefined): string | undefined {\n if (!code) return undefined;\n\n const info = getLocaleInfo(code);\n if (!info) return code;\n\n return `${info.nativeName} (${code.toLowerCase()})`;\n}\n\n/**\n * Get all supported locale codes\n */\nexport function getAllLocaleCodes(): readonly string[] {\n return LOCALES.map(l => l.code);\n}\n","/**\n * Helper functions for working with W3C ResourceDescriptor\n */\n\nimport type { components } from '@semiont/core';\n\ntype ResourceDescriptor = components['schemas']['ResourceDescriptor'];\ntype Representation = components['schemas']['Representation'];\n\n/**\n * Get the resource ID from @id property\n *\n * @id is always a bare ID (UUID), never a full URI.\n */\nexport function getResourceId(resource: ResourceDescriptor | undefined): string | undefined {\n if (!resource) return undefined;\n return resource['@id'] || undefined;\n}\n\n/**\n * Get the primary representation (first or only representation)\n */\nexport function getPrimaryRepresentation(resource: ResourceDescriptor | undefined): Representation | undefined {\n if (!resource?.representations) return undefined;\n const reps = Array.isArray(resource.representations)\n ? resource.representations\n : [resource.representations];\n return reps[0];\n}\n\n/**\n * Get the media type from the primary representation\n */\nexport function getPrimaryMediaType(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.mediaType;\n}\n\n/**\n * Get the checksum from the primary representation\n */\nexport function getChecksum(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.checksum;\n}\n\n/**\n * Get the language from the primary representation\n */\nexport function getLanguage(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.language;\n}\n\n/**\n * Get storage URI from primary representation\n *\n * @param resource - ResourceDescriptor\n * @returns Storage URI or undefined\n */\nexport function getStorageUri(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.storageUri;\n}\n\n/**\n * Get creator agent from wasAttributedTo\n * Handles both single agent and array of agents\n *\n * @param resource - ResourceDescriptor\n * @returns First agent or undefined\n */\nexport function getCreator(resource: ResourceDescriptor | undefined): components['schemas']['Agent'] | undefined {\n if (!resource?.wasAttributedTo) return undefined;\n\n return Array.isArray(resource.wasAttributedTo)\n ? resource.wasAttributedTo[0]\n : resource.wasAttributedTo;\n}\n\n/**\n * Get derived-from URI\n * Handles both single URI and array of URIs\n *\n * @param resource - ResourceDescriptor\n * @returns First derivation URI or undefined\n */\nexport function getDerivedFrom(resource: ResourceDescriptor | undefined): string | undefined {\n if (!resource?.wasDerivedFrom) return undefined;\n\n return Array.isArray(resource.wasDerivedFrom)\n ? resource.wasDerivedFrom[0]\n : resource.wasDerivedFrom;\n}\n\n/**\n * Check if resource is archived (application-specific field)\n *\n * @param resource - ResourceDescriptor\n * @returns True if archived, false otherwise\n */\nexport function isArchived(resource: ResourceDescriptor | undefined): boolean {\n return resource?.archived === true;\n}\n\n/**\n * Get entity types from resource (application-specific field)\n *\n * @param resource - ResourceDescriptor\n * @returns Array of entity types, empty if not set\n */\nexport function getResourceEntityTypes(resource: ResourceDescriptor | undefined): string[] {\n return resource?.entityTypes || [];\n}\n\n/**\n * Check if resource is a draft (application-specific field)\n *\n * @param resource - ResourceDescriptor\n * @returns True if draft, false otherwise\n */\nexport function isDraft(resource: ResourceDescriptor | undefined): boolean {\n return resource?.isDraft === true;\n}\n\n/**\n * Map charset names to Node.js Buffer encoding names\n * Node.js Buffer.toString() supports: 'utf8', 'utf16le', 'latin1', 'base64', 'hex', 'ascii', 'binary', 'ucs2'\n *\n * @param charset - Charset name (e.g., \"UTF-8\", \"ISO-8859-1\", \"Windows-1252\")\n * @returns Node.js BufferEncoding\n */\nexport function getNodeEncoding(charset: string): BufferEncoding {\n const normalized = charset.toLowerCase().replace(/[-_]/g, '');\n\n // Map common charset names to Node.js encodings\n const charsetMap: Record<string, BufferEncoding> = {\n 'utf8': 'utf8',\n 'iso88591': 'latin1',\n 'latin1': 'latin1',\n 'ascii': 'ascii',\n 'usascii': 'ascii',\n 'utf16le': 'utf16le',\n 'ucs2': 'ucs2',\n 'binary': 'binary',\n 'windows1252': 'latin1', // Windows-1252 is a superset of Latin-1\n 'cp1252': 'latin1',\n };\n\n return charsetMap[normalized] || 'utf8';\n}\n\n/**\n * Decode a representation buffer to string using the correct charset\n * Extracts charset from media type and uses appropriate encoding\n *\n * @param buffer - The raw representation data\n * @param mediaType - Media type with optional charset (e.g., \"text/plain; charset=iso-8859-1\")\n * @returns Decoded string\n *\n * @example\n * ```typescript\n * const content = decodeRepresentation(buffer, \"text/plain; charset=utf-8\");\n * const legacy = decodeRepresentation(buffer, \"text/plain; charset=windows-1252\");\n * ```\n */\nexport function decodeRepresentation(buffer: Buffer, mediaType: string): string {\n // Extract charset from mediaType (e.g., \"text/plain; charset=iso-8859-1\")\n const charsetMatch = mediaType.match(/charset=([^\\s;]+)/i);\n const charset = (charsetMatch?.[1] || 'utf-8').toLowerCase();\n\n // Map to Node.js encoding\n const encoding = getNodeEncoding(charset);\n\n return buffer.toString(encoding);\n}\n","/**\n * SVG Utility Functions\n *\n * Utilities for creating, parsing, and manipulating W3C-compliant SVG selectors\n * for image annotation.\n */\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface BoundingBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Create W3C-compliant SVG rectangle selector\n */\nexport function createRectangleSvg(start: Point, end: Point): string {\n const x = Math.min(start.x, end.x);\n const y = Math.min(start.y, end.y);\n const width = Math.abs(end.x - start.x);\n const height = Math.abs(end.y - start.y);\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"${x}\" y=\"${y}\" width=\"${width}\" height=\"${height}\"/></svg>`;\n}\n\n/**\n * Create W3C-compliant SVG polygon selector\n */\nexport function createPolygonSvg(points: Point[]): string {\n if (points.length < 3) {\n throw new Error('Polygon requires at least 3 points');\n }\n\n const pointsStr = points.map(p => `${p.x},${p.y}`).join(' ');\n return `<svg xmlns=\"http://www.w3.org/2000/svg\"><polygon points=\"${pointsStr}\"/></svg>`;\n}\n\n/**\n * Create W3C-compliant SVG circle selector\n */\nexport function createCircleSvg(center: Point, radius: number): string {\n if (radius <= 0) {\n throw new Error('Circle radius must be positive');\n }\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"${center.x}\" cy=\"${center.y}\" r=\"${radius}\"/></svg>`;\n}\n\n/**\n * Parse SVG selector to extract shape type and data\n */\nexport function parseSvgSelector(svg: string): {\n type: 'rect' | 'polygon' | 'circle' | 'path';\n data: any;\n} | null {\n // Extract rectangle\n const rectMatch = svg.match(/<rect\\s+([^>]+)\\/>/);\n if (rectMatch && rectMatch[1]) {\n const attrs = rectMatch[1];\n const x = parseFloat(attrs.match(/x=\"([^\"]+)\"/)?.[1] || '0');\n const y = parseFloat(attrs.match(/y=\"([^\"]+)\"/)?.[1] || '0');\n const width = parseFloat(attrs.match(/width=\"([^\"]+)\"/)?.[1] || '0');\n const height = parseFloat(attrs.match(/height=\"([^\"]+)\"/)?.[1] || '0');\n\n return {\n type: 'rect',\n data: { x, y, width, height }\n };\n }\n\n // Extract polygon\n const polygonMatch = svg.match(/<polygon\\s+points=\"([^\"]+)\"/);\n if (polygonMatch && polygonMatch[1]) {\n const pointsStr = polygonMatch[1];\n const points = pointsStr.split(/\\s+/).map(pair => {\n const [x, y] = pair.split(',').map(parseFloat);\n return { x, y };\n });\n\n return {\n type: 'polygon',\n data: { points }\n };\n }\n\n // Extract circle\n const circleMatch = svg.match(/<circle\\s+([^>]+)\\/>/);\n if (circleMatch && circleMatch[1]) {\n const attrs = circleMatch[1];\n const cx = parseFloat(attrs.match(/cx=\"([^\"]+)\"/)?.[1] || '0');\n const cy = parseFloat(attrs.match(/cy=\"([^\"]+)\"/)?.[1] || '0');\n const r = parseFloat(attrs.match(/r=\"([^\"]+)\"/)?.[1] || '0');\n\n return {\n type: 'circle',\n data: { cx, cy, r }\n };\n }\n\n return null;\n}\n\n/**\n * Normalize coordinates from display space to image native resolution\n */\nexport function normalizeCoordinates(\n point: Point,\n displayWidth: number,\n displayHeight: number,\n imageWidth: number,\n imageHeight: number\n): Point {\n return {\n x: (point.x / displayWidth) * imageWidth,\n y: (point.y / displayHeight) * imageHeight\n };\n}\n\n/**\n * Scale entire SVG selector from display space to image native resolution\n */\nexport function scaleSvgToNative(\n svg: string,\n displayWidth: number,\n displayHeight: number,\n imageWidth: number,\n imageHeight: number\n): string {\n const parsed = parseSvgSelector(svg);\n if (!parsed) return svg;\n\n const scaleX = imageWidth / displayWidth;\n const scaleY = imageHeight / displayHeight;\n\n switch (parsed.type) {\n case 'rect': {\n const { x, y, width, height } = parsed.data;\n return createRectangleSvg(\n { x: x * scaleX, y: y * scaleY },\n { x: (x + width) * scaleX, y: (y + height) * scaleY }\n );\n }\n\n case 'circle': {\n const { cx, cy, r } = parsed.data;\n return createCircleSvg(\n { x: cx * scaleX, y: cy * scaleY },\n r * Math.min(scaleX, scaleY)\n );\n }\n\n case 'polygon': {\n const points = parsed.data.points.map((p: Point) => ({\n x: p.x * scaleX,\n y: p.y * scaleY\n }));\n return createPolygonSvg(points);\n }\n }\n\n return svg;\n}\n","/**\n * Text context extraction utilities for W3C Web Annotation TextQuoteSelector\n *\n * Provides robust prefix/suffix context extraction with word boundary detection\n * to ensure fuzzy anchoring works correctly when the same text appears multiple times.\n *\n * Also provides AI offset validation and correction for handling AI-generated annotations\n * where the model may return slightly incorrect character offsets.\n *\n * @see https://www.w3.org/TR/annotation-model/#text-quote-selector\n */\n\nimport { findBestTextMatch, buildContentCache, type MatchQuality } from './fuzzy-anchor';\n\n/**\n * Extract prefix and suffix context for TextQuoteSelector\n *\n * Extracts up to 64 characters before and after the selected text,\n * extending to word boundaries to avoid cutting words in half.\n * This ensures prefix/suffix are meaningful context for fuzzy anchoring.\n *\n * @param content - Full text content\n * @param start - Start offset of selection\n * @param end - End offset of selection\n * @returns Object with prefix and suffix (undefined if at boundaries)\n *\n * @example\n * ```typescript\n * const content = \"The United States Congress...\";\n * const context = extractContext(content, 4, 17); // \"United States\"\n * // Returns: { prefix: \"The \", suffix: \" Congress...\" }\n * // NOT: { prefix: \"nited \", suffix: \"gress...\" }\n * ```\n */\nexport function extractContext(\n content: string,\n start: number,\n end: number\n): { prefix?: string; suffix?: string } {\n const CONTEXT_LENGTH = 64;\n const MAX_EXTENSION = 32; // Maximum additional chars to extend for word boundary\n\n // Extract prefix (up to CONTEXT_LENGTH chars before start, extended to word boundary)\n let prefix: string | undefined;\n if (start > 0) {\n let prefixStart = Math.max(0, start - CONTEXT_LENGTH);\n\n // Extend backward to word boundary (whitespace or punctuation)\n // Stop if we hit start of content or exceed MAX_EXTENSION\n let extensionCount = 0;\n while (prefixStart > 0 && extensionCount < MAX_EXTENSION) {\n const char = content[prefixStart - 1];\n // Break on whitespace, punctuation, or common delimiters\n if (!char || /[\\s.,;:!?'\"()\\[\\]{}<>\\/\\\\]/.test(char)) {\n break;\n }\n prefixStart--;\n extensionCount++;\n }\n\n prefix = content.substring(prefixStart, start);\n }\n\n // Extract suffix (up to CONTEXT_LENGTH chars after end, extended to word boundary)\n let suffix: string | undefined;\n if (end < content.length) {\n let suffixEnd = Math.min(content.length, end + CONTEXT_LENGTH);\n\n // Extend forward to word boundary (whitespace or punctuation)\n // Stop if we hit end of content or exceed MAX_EXTENSION\n let extensionCount = 0;\n while (suffixEnd < content.length && extensionCount < MAX_EXTENSION) {\n const char = content[suffixEnd];\n // Break on whitespace, punctuation, or common delimiters\n if (!char || /[\\s.,;:!?'\"()\\[\\]{}<>\\/\\\\]/.test(char)) {\n break;\n }\n suffixEnd++;\n extensionCount++;\n }\n\n suffix = content.substring(end, suffixEnd);\n }\n\n return { prefix, suffix };\n}\n\n/**\n * Result of validating and correcting AI-provided annotation offsets\n */\nexport interface ValidatedAnnotation {\n start: number;\n end: number;\n exact: string;\n prefix?: string;\n suffix?: string;\n corrected: boolean; // True if offsets were adjusted from AI's original values\n fuzzyMatched?: boolean; // True if we had to use fuzzy matching (minor text differences)\n matchQuality?: MatchQuality; // How we found the match\n}\n\n\n/**\n * Validate and correct AI-provided annotation offsets with fuzzy matching tolerance\n *\n * AI models sometimes return offsets that don't match the actual text position,\n * or provide text with minor variations (case differences, whitespace, typos).\n *\n * This function uses a multi-strategy approach:\n * 1. Check if AI's offsets are exactly correct\n * 2. Try exact case-sensitive search\n * 3. Try case-insensitive search\n * 4. Try fuzzy matching with Levenshtein distance (5% tolerance)\n *\n * This ensures we're maximally tolerant of AI errors while still maintaining\n * annotation quality and logging what corrections were made.\n *\n * @param content - Full text content\n * @param aiStart - Start offset from AI\n * @param aiEnd - End offset from AI\n * @param exact - The exact text that should be at this position (from AI)\n * @returns Validated annotation with corrected offsets and context\n * @throws Error if no acceptable match can be found\n *\n * @example\n * ```typescript\n * // AI said start=1143, but actual text is at 1161\n * const result = validateAndCorrectOffsets(\n * content,\n * 1143,\n * 1289,\n * \"the question \\\"whether...\"\n * );\n * // Returns: { start: 1161, end: 1303, exact: \"...\", corrected: true, matchQuality: 'exact', ... }\n * ```\n */\nexport function validateAndCorrectOffsets(\n content: string,\n aiStart: number,\n aiEnd: number,\n exact: string\n): ValidatedAnnotation {\n // First, check if AI's offsets are correct\n const textAtOffset = content.substring(aiStart, aiEnd);\n\n if (textAtOffset === exact) {\n // AI got it right! Just add proper context\n const context = extractContext(content, aiStart, aiEnd);\n return {\n start: aiStart,\n end: aiEnd,\n exact,\n prefix: context.prefix,\n suffix: context.suffix,\n corrected: false,\n matchQuality: 'exact'\n };\n }\n\n // AI's offsets are wrong - try to find the text using multiple strategies\n const cache = buildContentCache(content);\n const match = findBestTextMatch(content, exact, aiStart, cache);\n\n if (!match) {\n throw new Error(\n 'Cannot find acceptable match for text in content. ' +\n 'All search strategies failed. Text may be hallucinated.'\n );\n }\n\n // Found a match! Extract the actual text from content\n const actualText = content.substring(match.start, match.end);\n\n // Extract context using corrected offsets\n const context = extractContext(content, match.start, match.end);\n\n return {\n start: match.start,\n end: match.end,\n exact: actualText, // Use actual text from document, not AI's version\n prefix: context.prefix,\n suffix: context.suffix,\n corrected: true,\n fuzzyMatched: match.matchQuality !== 'exact',\n matchQuality: match.matchQuality\n };\n}\n","/**\n * Text encoding utilities for consistent charset handling\n *\n * Ensures frontend decoding matches backend decoding by respecting\n * charset parameters in mediaType (e.g., \"text/plain; charset=iso-8859-1\")\n */\n\n/**\n * Extract charset from mediaType parameter\n *\n * @param mediaType - Media type with optional charset (e.g., \"text/plain; charset=utf-8\")\n * @returns Charset name in lowercase (defaults to \"utf-8\")\n *\n * @example\n * extractCharset(\"text/plain; charset=iso-8859-1\") // \"iso-8859-1\"\n * extractCharset(\"text/plain\") // \"utf-8\"\n */\nexport function extractCharset(mediaType: string): string {\n const charsetMatch = mediaType.match(/charset=([^\\s;]+)/i);\n return (charsetMatch?.[1] || 'utf-8').toLowerCase();\n}\n\n/**\n * Decode ArrayBuffer to string using charset from mediaType\n *\n * Uses TextDecoder with the charset extracted from mediaType parameter.\n * This ensures the same character space is used for both annotation creation\n * (backend) and rendering (frontend).\n *\n * @param buffer - Binary data to decode\n * @param mediaType - Media type with optional charset parameter\n * @returns Decoded string in the original character space\n *\n * @example\n * const buffer = new Uint8Array([...]);\n * const text = decodeWithCharset(buffer, \"text/plain; charset=iso-8859-1\");\n */\nexport function decodeWithCharset(buffer: ArrayBuffer, mediaType: string): string {\n const charset = extractCharset(mediaType);\n\n // TextDecoder supports standard charset names\n // Common mappings that work in browsers:\n // - utf-8, utf-16, utf-16le, utf-16be\n // - iso-8859-1 through iso-8859-15\n // - windows-1252, windows-1251, etc.\n const decoder = new TextDecoder(charset);\n return decoder.decode(buffer);\n}\n","/**\n * Generic validation utilities for @semiont/api-client\n *\n * Pure TypeScript validation with no external dependencies.\n * Safe to use in any JavaScript environment (Node.js, browser, Deno, etc.)\n */\n\n/**\n * Validation result types\n */\nexport type ValidationSuccess<T> = { success: true; data: T };\nexport type ValidationFailure = { success: false; error: string; details?: string[] };\nexport type ValidationResult<T> = ValidationSuccess<T> | ValidationFailure;\n\n/**\n * JWT Token validation\n *\n * Validates JWT token format (header.payload.signature).\n * Does not verify signature - use for format validation only.\n */\nexport const JWTTokenSchema = {\n parse(token: unknown): string {\n if (typeof token !== 'string') {\n throw new Error('Token must be a string');\n }\n if (!token || token.length === 0) {\n throw new Error('Token is required');\n }\n // JWT format: header.payload.signature\n const jwtRegex = /^[A-Za-z0-9\\-_]+\\.[A-Za-z0-9\\-_]+\\.[A-Za-z0-9\\-_]*$/;\n if (!jwtRegex.test(token)) {\n throw new Error('Invalid JWT token format');\n }\n return token;\n },\n\n safeParse(token: unknown): ValidationResult<string> {\n try {\n const validated = this.parse(token);\n return { success: true, data: validated };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Invalid JWT token',\n };\n }\n },\n};\n\n/**\n * Generic validation helper with error formatting\n *\n * Wraps any schema's parse method with try/catch and returns ValidationResult.\n *\n * @example\n * ```typescript\n * const result = validateData(JWTTokenSchema, 'eyJ...');\n * if (result.success) {\n * console.log('Valid token:', result.data);\n * } else {\n * console.error('Invalid:', result.error);\n * }\n * ```\n */\nexport function validateData<T>(\n schema: { parse(data: unknown): T },\n data: unknown\n): ValidationResult<T> {\n try {\n const validated = schema.parse(data);\n return { success: true, data: validated };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Validation failed',\n };\n }\n}\n\n/**\n * Email validation helper\n *\n * Validates email format using RFC 5322 simplified regex.\n *\n * @param email - Email address to validate\n * @returns true if valid email format\n */\nexport function isValidEmail(email: string): boolean {\n if (email.length < 1 || email.length > 255) {\n return false;\n }\n // RFC 5322 simplified email regex\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(email);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@semiont/api-client",
3
- "version": "0.2.45",
3
+ "version": "0.3.0",
4
4
  "description": "Semiont API SDK - types, client, and utilities",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -8,11 +8,13 @@
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js"
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
12
13
  },
13
14
  "./utils": {
14
15
  "types": "./dist/utils/index.d.ts",
15
- "import": "./dist/utils/index.js"
16
+ "import": "./dist/utils/index.js",
17
+ "default": "./dist/utils/index.js"
16
18
  }
17
19
  },
18
20
  "engines": {
@@ -43,14 +45,14 @@
43
45
  },
44
46
  "dependencies": {
45
47
  "@semiont/core": "*",
46
- "ky": "^1.2.0"
48
+ "ky": "^1.2.0",
49
+ "rxjs": "^7.8.1"
47
50
  },
48
51
  "devDependencies": {
49
- "@vitest/coverage-v8": "^3.0.0",
50
- "orval": "^8.5.2",
52
+ "@vitest/coverage-v8": "^4.1.0",
51
53
  "tsup": "^8.5.1",
52
54
  "typescript": "^5.6.3",
53
- "vitest": "^3.2.4"
55
+ "vitest": "^4.1.0"
54
56
  },
55
57
  "keywords": [
56
58
  "semiont",