@stll/folio-core 0.61.0 → 0.62.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.
Files changed (59) hide show
  1. package/dist/ai-edits/headless.js +13 -12
  2. package/dist/controller/noteEditorManager.d.ts +1 -1
  3. package/dist/display-list/build/imagePrimitives.js +26 -7
  4. package/dist/display-list/build/paragraphPrimitives.js +15 -2
  5. package/dist/display-list/dom/renderDisplayListToDom.js +8 -5
  6. package/dist/display-list/types.d.ts +7 -3
  7. package/dist/docx/groupDrawingParser.js +22 -12
  8. package/dist/i18n/messages/ar.gen.js +1 -0
  9. package/dist/i18n/messages/catalogs.gen.d.ts +17 -0
  10. package/dist/i18n/messages/catalogs.gen.js +17 -0
  11. package/dist/i18n/messages/cs.gen.js +1 -0
  12. package/dist/i18n/messages/de.gen.js +1 -0
  13. package/dist/i18n/messages/en.gen.js +1 -0
  14. package/dist/i18n/messages/es.gen.js +1 -0
  15. package/dist/i18n/messages/et.gen.js +1 -0
  16. package/dist/i18n/messages/fr.gen.js +1 -0
  17. package/dist/i18n/messages/he.gen.js +1 -0
  18. package/dist/i18n/messages/hi.gen.js +1 -0
  19. package/dist/i18n/messages/hu.gen.js +1 -0
  20. package/dist/i18n/messages/lt.gen.js +1 -0
  21. package/dist/i18n/messages/lv.gen.js +1 -0
  22. package/dist/i18n/messages/messages.gen.d.ts +1 -0
  23. package/dist/i18n/messages/pl.gen.js +1 -0
  24. package/dist/i18n/messages/pt-BR.gen.js +1 -0
  25. package/dist/i18n/messages/sk.gen.js +1 -0
  26. package/dist/i18n/messages/tr.gen.js +1 -0
  27. package/dist/i18n/messages/zh-CN.gen.js +1 -0
  28. package/dist/layout-bridge/convert/endnoteLayout.d.ts +1 -1
  29. package/dist/layout-bridge/convert/endnoteLayout.js +1 -3
  30. package/dist/layout-engine/index.js +2 -2
  31. package/dist/layout-engine/noteAreaFlow.d.ts +4 -4
  32. package/dist/layout-engine/noteAreaFlow.js +12 -6
  33. package/dist/layout-engine/types.d.ts +5 -2
  34. package/dist/layout-painter/index.d.ts +1 -1
  35. package/dist/managers/FindReplaceManager.d.ts +13 -6
  36. package/dist/managers/FindReplaceManager.js +15 -9
  37. package/dist/paged-layout/editorScrollRoot.d.ts +3 -1
  38. package/dist/paged-layout/editorScrollRoot.js +2 -2
  39. package/dist/pdf/images.js +1 -0
  40. package/dist/prosemirror/commentRangeInlineAtoms.d.ts +40 -0
  41. package/dist/prosemirror/commentRangeInlineAtoms.js +33 -0
  42. package/dist/prosemirror/conversion/fromProseDoc.js +5 -4
  43. package/dist/prosemirror/conversion/toProseDoc.js +12 -19
  44. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +4 -4
  45. package/dist/prosemirror/fieldRepresentation.js +4 -2
  46. package/dist/prosemirror/findReplaceSelection.d.ts +38 -2
  47. package/dist/prosemirror/findReplaceSelection.js +143 -42
  48. package/dist/prosemirror/inlineDisplayText.d.ts +10 -0
  49. package/dist/prosemirror/inlineDisplayText.js +29 -0
  50. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -1
  51. package/dist/prosemirror/trackedRunInlineAtoms.js +1 -1
  52. package/dist/utils/findMatchView.d.ts +32 -0
  53. package/dist/utils/findMatchView.js +406 -0
  54. package/dist/utils/findReplace.d.ts +62 -4
  55. package/dist/utils/findReplace.js +359 -37
  56. package/dist/utils/findSearchKey.d.ts +29 -0
  57. package/dist/utils/findSearchKey.js +34 -0
  58. package/dist/utils/replaceText.js +138 -111
  59. package/package.json +1 -1
@@ -1698,7 +1698,17 @@ var FolioDocxReviewer = class FolioDocxReviewer {
1698
1698
  resolvedStoryExpectations: [...this.resolvedStoryExpectations.values()].filter(({ story }) => story.type === "main" || this.secondaryStorySource(story) !== void 0)
1699
1699
  };
1700
1700
  }
1701
- documentFromStateSnapshot(snapshot) {
1701
+ documentFromStateSnapshot(authored) {
1702
+ const pendingCommentIds = new Set(this.exportPendingSuggestions().flatMap(({ commentId }) => commentId === void 0 ? [] : [commentId]));
1703
+ const snapshot = {
1704
+ ...authored,
1705
+ mainState: withoutPendingSuggestionCommentMarks(rejectSuggestions(authored.mainState), pendingCommentIds),
1706
+ secondaryStoryStates: authored.secondaryStoryStates.map((entry) => ({
1707
+ ...entry,
1708
+ state: withoutPendingSuggestionCommentMarks(rejectSuggestions(entry.state), pendingCommentIds)
1709
+ })),
1710
+ createdComments: authored.createdComments.filter(({ id }) => !pendingCommentIds.has(id))
1711
+ };
1702
1712
  const sourceDocument = snapshot.importedStyles === void 0 ? this.baseDocument : {
1703
1713
  ...this.baseDocument,
1704
1714
  package: {
@@ -1739,7 +1749,6 @@ var FolioDocxReviewer = class FolioDocxReviewer {
1739
1749
  }
1740
1750
  captureSaveSnapshot() {
1741
1751
  const snapshot = this.captureReviewerState();
1742
- const pendingCommentIds = new Set(this.exportPendingSuggestions().flatMap(({ commentId }) => commentId === void 0 ? [] : [commentId]));
1743
1752
  const changedParaIds = new Set(getChangedParagraphIds(snapshot.mainState));
1744
1753
  let structuralChange = hasStructuralChanges(snapshot.mainState) || snapshot.finalSectionPropertiesOverride !== void 0 || snapshot.importedStyles !== void 0 || snapshot.importedHeaders.size > 0 || snapshot.importedFooters.size > 0 || snapshot.removedNoteStories.length > 0;
1745
1754
  let untrackedChanges = hasUntrackedChanges(snapshot.mainState);
@@ -1766,15 +1775,7 @@ var FolioDocxReviewer = class FolioDocxReviewer {
1766
1775
  reason: "untrackedChange"
1767
1776
  };
1768
1777
  return {
1769
- document: this.documentFromStateSnapshot({
1770
- ...snapshot,
1771
- mainState: withoutPendingSuggestionCommentMarks(rejectSuggestions(snapshot.mainState), pendingCommentIds),
1772
- secondaryStoryStates: snapshot.secondaryStoryStates.map((entry) => ({
1773
- ...entry,
1774
- state: withoutPendingSuggestionCommentMarks(rejectSuggestions(entry.state), pendingCommentIds)
1775
- })),
1776
- createdComments: snapshot.createdComments.filter(({ id }) => !pendingCommentIds.has(id))
1777
- }),
1778
+ document: this.documentFromStateSnapshot(snapshot),
1778
1779
  path,
1779
1780
  changedNoteParaIds,
1780
1781
  sectionReferenceRemovals: snapshot.sectionReferenceRemovals,
@@ -2050,7 +2051,7 @@ var FolioDocxReviewer = class FolioDocxReviewer {
2050
2051
  * same states, so the text now describes exactly what a save would write.
2051
2052
  */
2052
2053
  storyBlocks(state, source) {
2053
- return state ? proseDocToBlocks(state.doc, source.content, this.baseDocument.package.styles) : source.content;
2054
+ return state ? proseDocToBlocks(rejectSuggestions(state).doc, source.content, this.baseDocument.package.styles) : source.content;
2054
2055
  }
2055
2056
  getHeaderFooterStoryText(story, source) {
2056
2057
  const state = this.secondaryStoryStates.get(headerFooterStoryKey(story))?.state;
@@ -1,7 +1,7 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { CanonicalGap } from "../types/canonicalCapabilities.js";
3
- import { HiddenEditorApi } from "./hiddenEditorApi.js";
4
3
  import { NoteStoryKey } from "../types/editor-story.js";
4
+ import { HiddenEditorApi } from "./hiddenEditorApi.js";
5
5
  import { Plugin } from "prosemirror-state";
6
6
  import { DirectEditorProps, EditorView } from "prosemirror-view";
7
7
  //#region src/controller/noteEditorManager.d.ts
@@ -1,6 +1,6 @@
1
1
  import { parseRotationDegrees } from "../../utils/rotationBoundingBox.js";
2
2
  import { sanitizeImageSrc } from "../../utils/sanitizeImageSrc.js";
3
- import { base64ToBytes } from "../../utils/textEncoding.js";
3
+ import { base64ToBytes, encodeUtf8 } from "../../utils/textEncoding.js";
4
4
  import { paintPreview } from "./previewPrimitives.js";
5
5
  import { resolveBorderStroke } from "./strokes.js";
6
6
  import { UNSUPPORTED_CONSTRUCT } from "./unsupported.js";
@@ -11,12 +11,12 @@ import { Result } from "better-result";
11
11
  *
12
12
  * The display list carries raw bytes plus the format they are already in, so a
13
13
  * backend never owns a codec. This module therefore decodes only far enough to
14
- * fill `pixelWidth`/`pixelHeight` and to know PNG from JPEG. It transcodes
15
- * nothing: a WMF, EMF, TIFF, SVG, GIF or BMP source is reported through
16
- * `unsupported` and paints nothing, because a silently missing picture is worse
17
- * than a named one.
14
+ * fill `pixelWidth`/`pixelHeight` and identify PNG, JPEG, or a generated SVG
15
+ * preview. It transcodes nothing: WMF, EMF, TIFF, GIF, and BMP are reported
16
+ * through `unsupported` and paint nothing, because a silently missing picture
17
+ * is worse than a named one.
18
18
  */
19
- const DATA_URL_PATTERN = /^data:([^;,]*)(;base64)?,(.*)$/su;
19
+ const DATA_URL_PATTERN = /^data:([^;,]*)(?:;charset=[^;,]*)?(;base64)?,(.*)$/su;
20
20
  /**
21
21
  * `undefined` for a payload `atob` rejects: a malformed `data:` URL is a
22
22
  * document the builder reports, not an exception that aborts the build.
@@ -161,7 +161,26 @@ var ImageTable = class {
161
161
  if (safeSrc === void 0) return fail("image source is not a data: or blob: URL");
162
162
  const match = DATA_URL_PATTERN.exec(safeSrc);
163
163
  if (!match) return fail("image bytes are not inline (blob: URLs need a fetch the builder cannot do)");
164
- if (match[2] === void 0) return fail("only base64 data: URLs carry decodable bytes");
164
+ if (match[1] === "image/svg+xml" && match[2] === void 0) {
165
+ const decoded = Result.try(() => decodeURIComponent(match[3]));
166
+ if (decoded.isErr()) return fail("SVG data: URL payload is not valid percent-encoding");
167
+ if (!decoded.value.includes("data-folio-preview=\"wpGroup\"")) return fail("SVG is not a supported generated group preview");
168
+ const width = /<svg\b[^>]*\bwidth="([0-9.]+)"/u.exec(decoded.value)?.at(1);
169
+ const height = /<svg\b[^>]*\bheight="([0-9.]+)"/u.exec(decoded.value)?.at(1);
170
+ const pixelWidth = width === void 0 ? 0 : Number(width);
171
+ const pixelHeight = height === void 0 ? 0 : Number(height);
172
+ if (!(pixelWidth > 0 && pixelHeight > 0)) return fail("SVG carries no positive numeric width and height");
173
+ const ref = this.sources.length;
174
+ this.sources.push({
175
+ format: "svg",
176
+ bytes: encodeUtf8(decoded.value),
177
+ pixelWidth,
178
+ pixelHeight
179
+ });
180
+ this.refBySrc.set(src, ref);
181
+ return ref;
182
+ }
183
+ if (match[2] === void 0) return fail("only base64 data: URLs and SVG previews carry decodable bytes");
165
184
  const bytes = decodeBase64(match[3]);
166
185
  if (bytes === void 0) return fail("image data: URL payload is not valid base64");
167
186
  if (bytes.length === 0) return fail("image data: URL decoded to no bytes");
@@ -353,7 +353,7 @@ const smallCapsGlyphRunSegments = (glyphs, fontSizePx) => {
353
353
  * first, then the glyphs, then the decorations whose geometry CSS would have
354
354
  * derived from the font.
355
355
  */
356
- const emitGlyphRun = ({ sink, context, run, glyphs, style, paintXPx, baselineYPx, lineTopYPx, lineHeightPx, isRtl, pmRange, collapsedEdge }) => {
356
+ const emitGlyphRun = ({ sink, context, run, glyphs, style, paintXPx, baselineYPx, lineTopYPx, lineHeightPx, isRtl, pmRange, decorationRange, collapsedEdge }) => {
357
357
  if (glyphs.text.length === 0) return;
358
358
  const fontSizePx = ptToPx(style.fontSize ?? 11);
359
359
  const color = resolveRunColor(run, context);
@@ -423,6 +423,7 @@ const emitGlyphRun = ({ sink, context, run, glyphs, style, paintXPx, baselineYPx
423
423
  ...unicodeBidi === void 0 ? {} : { unicodeBidi },
424
424
  ...stroke === void 0 ? {} : { stroke },
425
425
  ...pmRange === void 0 ? {} : { pmRange },
426
+ ...decorationRange === void 0 ? {} : { decorationRange },
426
427
  ...collapsedEdge === void 0 ? {} : { collapsedEdge }
427
428
  };
428
429
  const smallCapsRuns = style.fontVariant === "small-caps" && direction === "ltr" ? smallCapsGlyphRunSegments(glyphs, fontSizePx) : void 0;
@@ -436,6 +437,7 @@ const emitGlyphRun = ({ sink, context, run, glyphs, style, paintXPx, baselineYPx
436
437
  else {
437
438
  const adjustments = glyphs.adjustments === void 0 ? {} : { adjustments: glyphs.adjustments };
438
439
  let segmentXPx = paintXPx;
440
+ let segmentTextOffset = 0;
439
441
  for (const segment of smallCapsRuns) {
440
442
  sink.glyphs.push({
441
443
  kind: "glyphRun",
@@ -446,9 +448,14 @@ const emitGlyphRun = ({ sink, context, run, glyphs, style, paintXPx, baselineYPx
446
448
  kerning: glyphs.kerning,
447
449
  smallCaps: true,
448
450
  ...adjustments,
449
- ...commonFields
451
+ ...commonFields,
452
+ ...decorationRange === void 0 ? {} : { decorationRange: {
453
+ ...decorationRange,
454
+ textOffset: decorationRange.textOffset + segmentTextOffset
455
+ } }
450
456
  });
451
457
  segmentXPx += segment.widthPx;
458
+ segmentTextOffset += segment.text.length;
452
459
  }
453
460
  }
454
461
  emitDecorations({
@@ -681,6 +688,12 @@ const paintLine = ({ block, line, geometry, context, alignment, isRtl, isFirstLi
681
688
  kind: "text",
682
689
  text: glyphs.text
683
690
  },
691
+ ...run.pmStart === void 0 || run.pmEnd === void 0 || resolveFieldText(run, context) !== run.fallback ? {} : { decorationRange: {
692
+ start: run.pmStart,
693
+ end: run.pmEnd,
694
+ story: context.story,
695
+ textOffset: 0
696
+ } },
684
697
  glyphs,
685
698
  style,
686
699
  paintXPx: paintXOf(),
@@ -48,7 +48,8 @@ const PAGE_ELEMENT_ID_PREFIX = "page-";
48
48
  const DEGREES_PER_RADIAN = 180 / Math.PI;
49
49
  const IMAGE_MIME_TYPES = {
50
50
  png: "image/png",
51
- jpeg: "image/jpeg"
51
+ jpeg: "image/jpeg",
52
+ svg: "image/svg+xml"
52
53
  };
53
54
  /**
54
55
  * The display list does not say whether an embedded face is sfnt or WOFF, so a
@@ -252,11 +253,11 @@ const applyAdjustments = (span, adjustments) => {
252
253
  * and in each note, so a surface has to know which one it landed in before it
253
254
  * can use the number at all.
254
255
  */
255
- const applyModelRange = (span, range) => {
256
+ const applyModelRange = (span, range, purpose = "editing") => {
256
257
  if (range === void 0) return;
257
- span.className = "layout-run-text";
258
- span.dataset["pmStart"] = String(range.start);
259
- span.dataset["pmEnd"] = String(range.end);
258
+ if (purpose === "editing") span.className = "layout-run-text";
259
+ span.dataset[purpose === "editing" ? "pmStart" : "decorationStart"] = String(range.start);
260
+ span.dataset[purpose === "editing" ? "pmEnd" : "decorationEnd"] = String(range.end);
260
261
  const { story } = range;
261
262
  span.dataset["story"] = story.kind;
262
263
  switch (story.kind) {
@@ -300,6 +301,8 @@ const paintGlyphRun = (run, context) => {
300
301
  applyAdjustments(span, run.adjustments);
301
302
  span.dataset["advanceSum"] = String(advanceSum);
302
303
  applyModelRange(span, run.pmRange);
304
+ applyModelRange(span, run.decorationRange, "decoration");
305
+ if (run.decorationRange) span.dataset["decorationTextOffset"] = String(run.decorationRange.textOffset);
303
306
  if (run.collapsedEdge !== void 0) {
304
307
  span.dataset[run.collapsedEdge.side === "leading" ? "collapsedLeadingSpaces" : "collapsedTrailingSpaces"] = "true";
305
308
  span.dataset["collapsedSpaceAdvance"] = String(run.collapsedEdge.spaceAdvancePx);
@@ -124,11 +124,11 @@ type DisplayFontRef = number;
124
124
  type DisplayImageRef = number;
125
125
  /**
126
126
  * Raw image bytes plus the format they are already in. `png` and `jpeg`
127
- * pass through to PDF unchanged; every other source format is transcoded by
128
- * the producer, so a backend never owns a codec.
127
+ * pass through to PDF unchanged. SVG is retained for vector previews in the
128
+ * DOM backend; PDF reports it as unsupported rather than silently rasterizing.
129
129
  */
130
130
  type DisplayImageSource = {
131
- readonly format: "png" | "jpeg";
131
+ readonly format: "png" | "jpeg" | "svg";
132
132
  readonly bytes: Uint8Array;
133
133
  readonly pixelWidth: number;
134
134
  readonly pixelHeight: number;
@@ -278,6 +278,10 @@ type DisplayGlyphRun = {
278
278
  * substituted field value, a tab leader.
279
279
  */
280
280
  readonly pmRange?: DisplayModelRange;
281
+ /** Source atom for view-only decorations; never used for editing positions. */
282
+ readonly decorationRange?: DisplayModelRange & {
283
+ readonly textOffset: number;
284
+ };
281
285
  };
282
286
  /** An axis-aligned rectangle, filled and/or stroked. At least one is set. */
283
287
  type DisplayRectPrimitive = {
@@ -16,6 +16,11 @@ const CROP_SCALE = 1e5;
16
16
  const MAX_PATH_COMMANDS = 1e4;
17
17
  const MAX_TEXT_CHARACTERS = 2e4;
18
18
  const MAX_SVG_CHARACTERS = 1e6;
19
+ const NON_RENDERING_GROUP_CHILDREN = /* @__PURE__ */ new Set([
20
+ "cNvGrpSpPr",
21
+ "grpSpPr",
22
+ "extLst"
23
+ ]);
19
24
  const numericAttr = (element, name) => {
20
25
  const direct = parseNumericAttribute(element, null, name);
21
26
  if (direct !== void 0) return direct;
@@ -175,13 +180,14 @@ const renderPicture = (picture, index, rels, media) => {
175
180
  const clipId = `group-picture-${index}`;
176
181
  return `<defs><clipPath id="${clipId}"><rect x="${x}" y="${y}" width="${width}" height="${height}"/></clipPath></defs><g clip-path="url(#${clipId})">${image}</g>`;
177
182
  };
178
- const groupViewBox = (group, width, height) => {
179
- const transform = readTransform(findChildByLocalName(findChildByLocalName(group, "grpSpPr"), "xfrm"));
183
+ const effectiveRootTransform = (group, width, height) => {
184
+ const authored = readTransform(findChildByLocalName(findChildByLocalName(group, "grpSpPr"), "xfrm"));
180
185
  return {
181
- x: transform.childX,
182
- y: transform.childY,
183
- width: transform.childWidth > 0 ? transform.childWidth : width,
184
- height: transform.childHeight > 0 ? transform.childHeight : height
186
+ ...authored,
187
+ width: authored.width > 0 ? authored.width : width,
188
+ height: authored.height > 0 ? authored.height : height,
189
+ childWidth: authored.childWidth > 0 ? authored.childWidth : width,
190
+ childHeight: authored.childHeight > 0 ? authored.childHeight : height
185
191
  };
186
192
  };
187
193
  /**
@@ -226,20 +232,22 @@ const createSvg = (group, width, height, rels, media, hostedTextBoxes) => {
226
232
  if (nested === null) return null;
227
233
  piece = nested ? wrapTransformed(transform, `<g transform="${nestedGroupTransform(transform)}">${nested}</g>`) : "";
228
234
  total -= nested.length;
229
- } else continue;
235
+ } else if (NON_RENDERING_GROUP_CHILDREN.has(localName)) continue;
236
+ else return null;
230
237
  content += piece;
231
238
  total += piece.length;
232
239
  if (total > MAX_SVG_CHARACTERS) return null;
233
240
  }
234
241
  return content;
235
242
  };
236
- const viewBox = groupViewBox(group, width, height);
243
+ const root = effectiveRootTransform(group, width, height);
237
244
  const content = render(group, {
238
- x: width / viewBox.width,
239
- y: height / viewBox.height
245
+ x: root.width / root.childWidth,
246
+ y: root.height / root.childHeight
240
247
  }, 0);
241
248
  if (content === null || !content && hostedTextBoxes.size === 0) return null;
242
- return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}" width="${emuToPixels(width)}" height="${emuToPixels(height)}">${content}</svg>`;
249
+ const transformed = content ? wrapTransformed(root, `<g transform="${nestedGroupTransform(root)}">${content}</g>`) : "";
250
+ return `<svg xmlns="http://www.w3.org/2000/svg" data-folio-preview="wpGroup" viewBox="0 0 ${width} ${height}" width="${emuToPixels(width)}" height="${emuToPixels(height)}">${transformed}</svg>`;
243
251
  };
244
252
  const groupElement = (drawing) => {
245
253
  return findChildByLocalName(findAllDeep(drawing, "a", "graphicData").at(0) ?? null, "wgp");
@@ -273,7 +281,9 @@ const parseGroupDrawing = (drawing, previews, rels, media) => {
273
281
  if (!group) return null;
274
282
  const image = parseImage(drawing, void 0, void 0);
275
283
  if (!image || image.size.width <= 0 || image.size.height <= 0) return null;
276
- const hosted = hostsTextBoxes(image) ? collectGroupTextBoxes(group, image.size.width, image.size.height) : [];
284
+ const rootTransform = effectiveRootTransform(group, image.size.width, image.size.height);
285
+ const rootTurnsChildren = rootTransform.rotation !== 0 || rootTransform.flipH || rootTransform.flipV;
286
+ const hosted = hostsTextBoxes(image) && !rootTurnsChildren ? collectGroupTextBoxes(group, image.size.width, image.size.height) : [];
277
287
  const svg = createSvg(group, image.size.width, image.size.height, rels, media, new Set(hosted.map(({ wsp }) => wsp)));
278
288
  if (!svg || svg.length > MAX_SVG_CHARACTERS) return null;
279
289
  const { rId: _rId, src: _src, mimeType: _mimeType, filename: _filename, ...frame } = image;
@@ -362,6 +362,7 @@ const messages = { "folio": {
362
362
  "previous": "النتيجة السابقة",
363
363
  "previousShortcut": "النتيجة السابقة (Shift+Enter)",
364
364
  "replaceAll": "استبدال الكل",
365
+ "replaceAllSummary": "تم استبدال {replacedCount} وتخطي {skippedCount}",
365
366
  "replaceCurrent": "استبدال النتيجة الحالية",
366
367
  "replacePlaceholder": "نص الاستبدال...",
367
368
  "replaceText": "نص الاستبدال",
@@ -364,6 +364,7 @@ declare const CATALOGS: {
364
364
  readonly previous: "Previous match";
365
365
  readonly previousShortcut: "Previous match (Shift+Enter)";
366
366
  readonly replaceAll: "Replace all";
367
+ readonly replaceAllSummary: "{replacedCount} replaced, {skippedCount} skipped";
367
368
  readonly replaceCurrent: "Replace current match";
368
369
  readonly replacePlaceholder: "Replacement text...";
369
370
  readonly replaceText: "Replacement text";
@@ -1023,6 +1024,7 @@ declare const CATALOGS: {
1023
1024
  readonly previous: "Vorheriger Treffer";
1024
1025
  readonly previousShortcut: "Vorheriger Treffer (Shift+Enter)";
1025
1026
  readonly replaceAll: "Alle ersetzen";
1027
+ readonly replaceAllSummary: "{replacedCount} ersetzt, {skippedCount} übersprungen";
1026
1028
  readonly replaceCurrent: "Aktuellen Treffer ersetzen";
1027
1029
  readonly replacePlaceholder: "Ersatztext...";
1028
1030
  readonly replaceText: "Ersatztext";
@@ -1682,6 +1684,7 @@ declare const CATALOGS: {
1682
1684
  readonly previous: "Occurrence précédente";
1683
1685
  readonly previousShortcut: "Occurrence précédente (Maj+Entrée)";
1684
1686
  readonly replaceAll: "Tout remplacer";
1687
+ readonly replaceAllSummary: "{replacedCount} remplacés, {skippedCount} ignorés";
1685
1688
  readonly replaceCurrent: "Remplacer l’occurrence actuelle";
1686
1689
  readonly replacePlaceholder: "Texte de remplacement...";
1687
1690
  readonly replaceText: "Texte de remplacement";
@@ -2341,6 +2344,7 @@ declare const CATALOGS: {
2341
2344
  readonly previous: "Coincidencia anterior";
2342
2345
  readonly previousShortcut: "Coincidencia anterior (Shift+Enter)";
2343
2346
  readonly replaceAll: "Reemplazar todo";
2347
+ readonly replaceAllSummary: "{replacedCount} reemplazados, {skippedCount} omitidos";
2344
2348
  readonly replaceCurrent: "Reemplazar coincidencia actual";
2345
2349
  readonly replacePlaceholder: "Texto de reemplazo...";
2346
2350
  readonly replaceText: "Texto de reemplazo";
@@ -3000,6 +3004,7 @@ declare const CATALOGS: {
3000
3004
  readonly previous: "Předchozí výskyt";
3001
3005
  readonly previousShortcut: "Předchozí výskyt (Shift+Enter)";
3002
3006
  readonly replaceAll: "Nahradit vše";
3007
+ readonly replaceAllSummary: "Nahrazeno: {replacedCount}, přeskočeno: {skippedCount}";
3003
3008
  readonly replaceCurrent: "Nahradit aktuální výskyt";
3004
3009
  readonly replacePlaceholder: "Text náhrady...";
3005
3010
  readonly replaceText: "Text náhrady";
@@ -3659,6 +3664,7 @@ declare const CATALOGS: {
3659
3664
  readonly previous: "النتيجة السابقة";
3660
3665
  readonly previousShortcut: "النتيجة السابقة (Shift+Enter)";
3661
3666
  readonly replaceAll: "استبدال الكل";
3667
+ readonly replaceAllSummary: "تم استبدال {replacedCount} وتخطي {skippedCount}";
3662
3668
  readonly replaceCurrent: "استبدال النتيجة الحالية";
3663
3669
  readonly replacePlaceholder: "نص الاستبدال...";
3664
3670
  readonly replaceText: "نص الاستبدال";
@@ -4318,6 +4324,7 @@ declare const CATALOGS: {
4318
4324
  readonly previous: "Eelmine vaste";
4319
4325
  readonly previousShortcut: "Eelmine vaste (Shift+Enter)";
4320
4326
  readonly replaceAll: "Asenda kõik";
4327
+ readonly replaceAllSummary: "Asendatud: {replacedCount}, vahele jäetud: {skippedCount}";
4321
4328
  readonly replaceCurrent: "Asenda praegune vaste";
4322
4329
  readonly replacePlaceholder: "Asendustekst…";
4323
4330
  readonly replaceText: "Asendustekst";
@@ -4977,6 +4984,7 @@ declare const CATALOGS: {
4977
4984
  readonly previous: "ההתאמה הקודמת";
4978
4985
  readonly previousShortcut: "ההתאמה הקודמת (Shift+Enter)";
4979
4986
  readonly replaceAll: "החלף הכל";
4987
+ readonly replaceAllSummary: "הוחלפו {replacedCount}, דולגו {skippedCount}";
4980
4988
  readonly replaceCurrent: "החלף את התוצאה הנוכחית";
4981
4989
  readonly replacePlaceholder: "טקסט חלופי...";
4982
4990
  readonly replaceText: "טקסט חלופי";
@@ -5636,6 +5644,7 @@ declare const CATALOGS: {
5636
5644
  readonly previous: "पिछला मिलान";
5637
5645
  readonly previousShortcut: "पिछला मिलान (Shift+Enter)";
5638
5646
  readonly replaceAll: "सभी बदलें";
5647
+ readonly replaceAllSummary: "{replacedCount} बदले गए, {skippedCount} छोड़े गए";
5639
5648
  readonly replaceCurrent: "वर्तमान मिलान को बदलें";
5640
5649
  readonly replacePlaceholder: "बदलने वाला पाठ...";
5641
5650
  readonly replaceText: "बदलने वाला पाठ";
@@ -6295,6 +6304,7 @@ declare const CATALOGS: {
6295
6304
  readonly previous: "Előző találat";
6296
6305
  readonly previousShortcut: "Előző találat (Shift+Enter)";
6297
6306
  readonly replaceAll: "Összes cseréje";
6307
+ readonly replaceAllSummary: "Cserélve: {replacedCount}, kihagyva: {skippedCount}";
6298
6308
  readonly replaceCurrent: "Jelenlegi találat cseréje";
6299
6309
  readonly replacePlaceholder: "Csereszöveg…";
6300
6310
  readonly replaceText: "Csereszöveg";
@@ -6954,6 +6964,7 @@ declare const CATALOGS: {
6954
6964
  readonly previous: "Ankstesnis atitikmuo";
6955
6965
  readonly previousShortcut: "Ankstesnis atitikmuo (Shift+Enter)";
6956
6966
  readonly replaceAll: "Pakeisti viską";
6967
+ readonly replaceAllSummary: "Pakeista: {replacedCount}, praleista: {skippedCount}";
6957
6968
  readonly replaceCurrent: "Pakeisti dabartinį atitikmenį";
6958
6969
  readonly replacePlaceholder: "Pakeičiantysis tekstas…";
6959
6970
  readonly replaceText: "Pakeičiantysis tekstas";
@@ -7613,6 +7624,7 @@ declare const CATALOGS: {
7613
7624
  readonly previous: "Iepriekšējā atbilstība";
7614
7625
  readonly previousShortcut: "Iepriekšējā atbilstība (Shift+Enter)";
7615
7626
  readonly replaceAll: "Aizstāt visu";
7627
+ readonly replaceAllSummary: "Aizstāti: {replacedCount}, izlaisti: {skippedCount}";
7616
7628
  readonly replaceCurrent: "Aizstāt pašreizējo atbilstību";
7617
7629
  readonly replacePlaceholder: "Aizstājējteksts…";
7618
7630
  readonly replaceText: "Aizstājējteksts";
@@ -8272,6 +8284,7 @@ declare const CATALOGS: {
8272
8284
  readonly previous: "Poprzednie wystąpienie";
8273
8285
  readonly previousShortcut: "Poprzednie wystąpienie (Shift+Enter)";
8274
8286
  readonly replaceAll: "Zamień wszystko";
8287
+ readonly replaceAllSummary: "Zastąpiono: {replacedCount}, pominięto: {skippedCount}";
8275
8288
  readonly replaceCurrent: "Zamień bieżące wystąpienie";
8276
8289
  readonly replacePlaceholder: "Tekst zamienny...";
8277
8290
  readonly replaceText: "Tekst zamienny";
@@ -8931,6 +8944,7 @@ declare const CATALOGS: {
8931
8944
  readonly previous: "Ocorrência anterior";
8932
8945
  readonly previousShortcut: "Ocorrência anterior (Shift+Enter)";
8933
8946
  readonly replaceAll: "Substituir tudo";
8947
+ readonly replaceAllSummary: "{replacedCount} substituídos, {skippedCount} ignorados";
8934
8948
  readonly replaceCurrent: "Substituir correspondência atual";
8935
8949
  readonly replacePlaceholder: "Texto de substituição...";
8936
8950
  readonly replaceText: "Texto de substituição";
@@ -9590,6 +9604,7 @@ declare const CATALOGS: {
9590
9604
  readonly previous: "Predchádzajúci výskyt";
9591
9605
  readonly previousShortcut: "Predchádzajúci výskyt (Shift+Enter)";
9592
9606
  readonly replaceAll: "Nahradiť všetko";
9607
+ readonly replaceAllSummary: "Nahradené: {replacedCount}, preskočené: {skippedCount}";
9593
9608
  readonly replaceCurrent: "Nahradiť aktuálny výskyt";
9594
9609
  readonly replacePlaceholder: "Text náhrady...";
9595
9610
  readonly replaceText: "Text náhrady";
@@ -10249,6 +10264,7 @@ declare const CATALOGS: {
10249
10264
  readonly previous: "Önceki eşleşme";
10250
10265
  readonly previousShortcut: "Önceki eşleşme (Shift+Enter)";
10251
10266
  readonly replaceAll: "Tümünü değiştir";
10267
+ readonly replaceAllSummary: "{replacedCount} değiştirildi, {skippedCount} atlandı";
10252
10268
  readonly replaceCurrent: "Mevcut eşleşmeyi değiştir";
10253
10269
  readonly replacePlaceholder: "Yeni metin...";
10254
10270
  readonly replaceText: "Yeni metin";
@@ -10908,6 +10924,7 @@ declare const CATALOGS: {
10908
10924
  readonly previous: "上一个匹配项";
10909
10925
  readonly previousShortcut: "上一个匹配项 (Shift+Enter)";
10910
10926
  readonly replaceAll: "全部替换";
10927
+ readonly replaceAllSummary: "已替换 {replacedCount} 项,已跳过 {skippedCount} 项";
10911
10928
  readonly replaceCurrent: "替换当前匹配项";
10912
10929
  readonly replacePlaceholder: "替换为...";
10913
10930
  readonly replaceText: "替换文本";
@@ -363,6 +363,7 @@ const CATALOGS = {
363
363
  "previous": "Previous match",
364
364
  "previousShortcut": "Previous match (Shift+Enter)",
365
365
  "replaceAll": "Replace all",
366
+ "replaceAllSummary": "{replacedCount} replaced, {skippedCount} skipped",
366
367
  "replaceCurrent": "Replace current match",
367
368
  "replacePlaceholder": "Replacement text...",
368
369
  "replaceText": "Replacement text",
@@ -1020,6 +1021,7 @@ const CATALOGS = {
1020
1021
  "previous": "Vorheriger Treffer",
1021
1022
  "previousShortcut": "Vorheriger Treffer (Shift+Enter)",
1022
1023
  "replaceAll": "Alle ersetzen",
1024
+ "replaceAllSummary": "{replacedCount} ersetzt, {skippedCount} übersprungen",
1023
1025
  "replaceCurrent": "Aktuellen Treffer ersetzen",
1024
1026
  "replacePlaceholder": "Ersatztext...",
1025
1027
  "replaceText": "Ersatztext",
@@ -1677,6 +1679,7 @@ const CATALOGS = {
1677
1679
  "previous": "Occurrence précédente",
1678
1680
  "previousShortcut": "Occurrence précédente (Maj+Entrée)",
1679
1681
  "replaceAll": "Tout remplacer",
1682
+ "replaceAllSummary": "{replacedCount} remplacés, {skippedCount} ignorés",
1680
1683
  "replaceCurrent": "Remplacer l’occurrence actuelle",
1681
1684
  "replacePlaceholder": "Texte de remplacement...",
1682
1685
  "replaceText": "Texte de remplacement",
@@ -2334,6 +2337,7 @@ const CATALOGS = {
2334
2337
  "previous": "Coincidencia anterior",
2335
2338
  "previousShortcut": "Coincidencia anterior (Shift+Enter)",
2336
2339
  "replaceAll": "Reemplazar todo",
2340
+ "replaceAllSummary": "{replacedCount} reemplazados, {skippedCount} omitidos",
2337
2341
  "replaceCurrent": "Reemplazar coincidencia actual",
2338
2342
  "replacePlaceholder": "Texto de reemplazo...",
2339
2343
  "replaceText": "Texto de reemplazo",
@@ -2991,6 +2995,7 @@ const CATALOGS = {
2991
2995
  "previous": "Předchozí výskyt",
2992
2996
  "previousShortcut": "Předchozí výskyt (Shift+Enter)",
2993
2997
  "replaceAll": "Nahradit vše",
2998
+ "replaceAllSummary": "Nahrazeno: {replacedCount}, přeskočeno: {skippedCount}",
2994
2999
  "replaceCurrent": "Nahradit aktuální výskyt",
2995
3000
  "replacePlaceholder": "Text náhrady...",
2996
3001
  "replaceText": "Text náhrady",
@@ -3648,6 +3653,7 @@ const CATALOGS = {
3648
3653
  "previous": "النتيجة السابقة",
3649
3654
  "previousShortcut": "النتيجة السابقة (Shift+Enter)",
3650
3655
  "replaceAll": "استبدال الكل",
3656
+ "replaceAllSummary": "تم استبدال {replacedCount} وتخطي {skippedCount}",
3651
3657
  "replaceCurrent": "استبدال النتيجة الحالية",
3652
3658
  "replacePlaceholder": "نص الاستبدال...",
3653
3659
  "replaceText": "نص الاستبدال",
@@ -4305,6 +4311,7 @@ const CATALOGS = {
4305
4311
  "previous": "Eelmine vaste",
4306
4312
  "previousShortcut": "Eelmine vaste (Shift+Enter)",
4307
4313
  "replaceAll": "Asenda kõik",
4314
+ "replaceAllSummary": "Asendatud: {replacedCount}, vahele jäetud: {skippedCount}",
4308
4315
  "replaceCurrent": "Asenda praegune vaste",
4309
4316
  "replacePlaceholder": "Asendustekst…",
4310
4317
  "replaceText": "Asendustekst",
@@ -4962,6 +4969,7 @@ const CATALOGS = {
4962
4969
  "previous": "ההתאמה הקודמת",
4963
4970
  "previousShortcut": "ההתאמה הקודמת (Shift+Enter)",
4964
4971
  "replaceAll": "החלף הכל",
4972
+ "replaceAllSummary": "הוחלפו {replacedCount}, דולגו {skippedCount}",
4965
4973
  "replaceCurrent": "החלף את התוצאה הנוכחית",
4966
4974
  "replacePlaceholder": "טקסט חלופי...",
4967
4975
  "replaceText": "טקסט חלופי",
@@ -5619,6 +5627,7 @@ const CATALOGS = {
5619
5627
  "previous": "पिछला मिलान",
5620
5628
  "previousShortcut": "पिछला मिलान (Shift+Enter)",
5621
5629
  "replaceAll": "सभी बदलें",
5630
+ "replaceAllSummary": "{replacedCount} बदले गए, {skippedCount} छोड़े गए",
5622
5631
  "replaceCurrent": "वर्तमान मिलान को बदलें",
5623
5632
  "replacePlaceholder": "बदलने वाला पाठ...",
5624
5633
  "replaceText": "बदलने वाला पाठ",
@@ -6276,6 +6285,7 @@ const CATALOGS = {
6276
6285
  "previous": "Előző találat",
6277
6286
  "previousShortcut": "Előző találat (Shift+Enter)",
6278
6287
  "replaceAll": "Összes cseréje",
6288
+ "replaceAllSummary": "Cserélve: {replacedCount}, kihagyva: {skippedCount}",
6279
6289
  "replaceCurrent": "Jelenlegi találat cseréje",
6280
6290
  "replacePlaceholder": "Csereszöveg…",
6281
6291
  "replaceText": "Csereszöveg",
@@ -6933,6 +6943,7 @@ const CATALOGS = {
6933
6943
  "previous": "Ankstesnis atitikmuo",
6934
6944
  "previousShortcut": "Ankstesnis atitikmuo (Shift+Enter)",
6935
6945
  "replaceAll": "Pakeisti viską",
6946
+ "replaceAllSummary": "Pakeista: {replacedCount}, praleista: {skippedCount}",
6936
6947
  "replaceCurrent": "Pakeisti dabartinį atitikmenį",
6937
6948
  "replacePlaceholder": "Pakeičiantysis tekstas…",
6938
6949
  "replaceText": "Pakeičiantysis tekstas",
@@ -7590,6 +7601,7 @@ const CATALOGS = {
7590
7601
  "previous": "Iepriekšējā atbilstība",
7591
7602
  "previousShortcut": "Iepriekšējā atbilstība (Shift+Enter)",
7592
7603
  "replaceAll": "Aizstāt visu",
7604
+ "replaceAllSummary": "Aizstāti: {replacedCount}, izlaisti: {skippedCount}",
7593
7605
  "replaceCurrent": "Aizstāt pašreizējo atbilstību",
7594
7606
  "replacePlaceholder": "Aizstājējteksts…",
7595
7607
  "replaceText": "Aizstājējteksts",
@@ -8247,6 +8259,7 @@ const CATALOGS = {
8247
8259
  "previous": "Poprzednie wystąpienie",
8248
8260
  "previousShortcut": "Poprzednie wystąpienie (Shift+Enter)",
8249
8261
  "replaceAll": "Zamień wszystko",
8262
+ "replaceAllSummary": "Zastąpiono: {replacedCount}, pominięto: {skippedCount}",
8250
8263
  "replaceCurrent": "Zamień bieżące wystąpienie",
8251
8264
  "replacePlaceholder": "Tekst zamienny...",
8252
8265
  "replaceText": "Tekst zamienny",
@@ -8904,6 +8917,7 @@ const CATALOGS = {
8904
8917
  "previous": "Ocorrência anterior",
8905
8918
  "previousShortcut": "Ocorrência anterior (Shift+Enter)",
8906
8919
  "replaceAll": "Substituir tudo",
8920
+ "replaceAllSummary": "{replacedCount} substituídos, {skippedCount} ignorados",
8907
8921
  "replaceCurrent": "Substituir correspondência atual",
8908
8922
  "replacePlaceholder": "Texto de substituição...",
8909
8923
  "replaceText": "Texto de substituição",
@@ -9561,6 +9575,7 @@ const CATALOGS = {
9561
9575
  "previous": "Predchádzajúci výskyt",
9562
9576
  "previousShortcut": "Predchádzajúci výskyt (Shift+Enter)",
9563
9577
  "replaceAll": "Nahradiť všetko",
9578
+ "replaceAllSummary": "Nahradené: {replacedCount}, preskočené: {skippedCount}",
9564
9579
  "replaceCurrent": "Nahradiť aktuálny výskyt",
9565
9580
  "replacePlaceholder": "Text náhrady...",
9566
9581
  "replaceText": "Text náhrady",
@@ -10218,6 +10233,7 @@ const CATALOGS = {
10218
10233
  "previous": "Önceki eşleşme",
10219
10234
  "previousShortcut": "Önceki eşleşme (Shift+Enter)",
10220
10235
  "replaceAll": "Tümünü değiştir",
10236
+ "replaceAllSummary": "{replacedCount} değiştirildi, {skippedCount} atlandı",
10221
10237
  "replaceCurrent": "Mevcut eşleşmeyi değiştir",
10222
10238
  "replacePlaceholder": "Yeni metin...",
10223
10239
  "replaceText": "Yeni metin",
@@ -10875,6 +10891,7 @@ const CATALOGS = {
10875
10891
  "previous": "上一个匹配项",
10876
10892
  "previousShortcut": "上一个匹配项 (Shift+Enter)",
10877
10893
  "replaceAll": "全部替换",
10894
+ "replaceAllSummary": "已替换 {replacedCount} 项,已跳过 {skippedCount} 项",
10878
10895
  "replaceCurrent": "替换当前匹配项",
10879
10896
  "replacePlaceholder": "替换为...",
10880
10897
  "replaceText": "替换文本",
@@ -362,6 +362,7 @@ const messages = { "folio": {
362
362
  "previous": "Předchozí výskyt",
363
363
  "previousShortcut": "Předchozí výskyt (Shift+Enter)",
364
364
  "replaceAll": "Nahradit vše",
365
+ "replaceAllSummary": "Nahrazeno: {replacedCount}, přeskočeno: {skippedCount}",
365
366
  "replaceCurrent": "Nahradit aktuální výskyt",
366
367
  "replacePlaceholder": "Text náhrady...",
367
368
  "replaceText": "Text náhrady",
@@ -362,6 +362,7 @@ const messages = { "folio": {
362
362
  "previous": "Vorheriger Treffer",
363
363
  "previousShortcut": "Vorheriger Treffer (Shift+Enter)",
364
364
  "replaceAll": "Alle ersetzen",
365
+ "replaceAllSummary": "{replacedCount} ersetzt, {skippedCount} übersprungen",
365
366
  "replaceCurrent": "Aktuellen Treffer ersetzen",
366
367
  "replacePlaceholder": "Ersatztext...",
367
368
  "replaceText": "Ersatztext",
@@ -362,6 +362,7 @@ const messages = { "folio": {
362
362
  "previous": "Previous match",
363
363
  "previousShortcut": "Previous match (Shift+Enter)",
364
364
  "replaceAll": "Replace all",
365
+ "replaceAllSummary": "{replacedCount} replaced, {skippedCount} skipped",
365
366
  "replaceCurrent": "Replace current match",
366
367
  "replacePlaceholder": "Replacement text...",
367
368
  "replaceText": "Replacement text",
@@ -362,6 +362,7 @@ const messages = { "folio": {
362
362
  "previous": "Coincidencia anterior",
363
363
  "previousShortcut": "Coincidencia anterior (Shift+Enter)",
364
364
  "replaceAll": "Reemplazar todo",
365
+ "replaceAllSummary": "{replacedCount} reemplazados, {skippedCount} omitidos",
365
366
  "replaceCurrent": "Reemplazar coincidencia actual",
366
367
  "replacePlaceholder": "Texto de reemplazo...",
367
368
  "replaceText": "Texto de reemplazo",
@@ -362,6 +362,7 @@ const messages = { "folio": {
362
362
  "previous": "Eelmine vaste",
363
363
  "previousShortcut": "Eelmine vaste (Shift+Enter)",
364
364
  "replaceAll": "Asenda kõik",
365
+ "replaceAllSummary": "Asendatud: {replacedCount}, vahele jäetud: {skippedCount}",
365
366
  "replaceCurrent": "Asenda praegune vaste",
366
367
  "replacePlaceholder": "Asendustekst…",
367
368
  "replaceText": "Asendustekst",
@@ -362,6 +362,7 @@ const messages = { "folio": {
362
362
  "previous": "Occurrence précédente",
363
363
  "previousShortcut": "Occurrence précédente (Maj+Entrée)",
364
364
  "replaceAll": "Tout remplacer",
365
+ "replaceAllSummary": "{replacedCount} remplacés, {skippedCount} ignorés",
365
366
  "replaceCurrent": "Remplacer l’occurrence actuelle",
366
367
  "replacePlaceholder": "Texte de remplacement...",
367
368
  "replaceText": "Texte de remplacement",