@docx4j/core-ts 0.5.0 → 0.7.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.
- package/NOTICE +4 -0
- package/README.md +92 -4
- package/dist/html/convert.mjs +2 -1
- package/dist/html/elements.mjs +2 -1
- package/dist/model/color/ColorMath.d.mts +29 -0
- package/dist/model/color/ColorMath.mjs +146 -0
- package/dist/model/color/ColorTables.d.mts +6 -0
- package/dist/model/color/ColorTables.mjs +83 -0
- package/dist/model/color/DrawingMLColors.d.mts +52 -0
- package/dist/model/color/DrawingMLColors.mjs +374 -0
- package/dist/model/color/ResolvedColor.d.mts +36 -0
- package/dist/model/color/ResolvedColor.mjs +65 -0
- package/dist/model/color/SpreadsheetColors.d.mts +36 -0
- package/dist/model/color/SpreadsheetColors.mjs +84 -0
- package/dist/model/color/StyleFill.d.mts +28 -0
- package/dist/model/color/StyleFill.mjs +21 -0
- package/dist/model/color/ThemeColors.d.mts +86 -0
- package/dist/model/color/ThemeColors.mjs +304 -0
- package/dist/model/color/WordColors.d.mts +71 -0
- package/dist/model/color/WordColors.mjs +121 -0
- package/dist/model/color/index.d.mts +6 -0
- package/dist/model/color/index.mjs +30 -0
- package/dist/model/content/Body.d.mts +145 -23
- package/dist/model/content/Body.mjs +507 -150
- package/dist/model/content/Comment.d.mts +23 -5
- package/dist/model/content/Comment.mjs +207 -26
- package/dist/model/content/ContentControl.d.mts +198 -19
- package/dist/model/content/ContentControl.mjs +672 -99
- package/dist/model/content/Font.d.mts +70 -17
- package/dist/model/content/Font.mjs +119 -36
- package/dist/model/content/InlinePicture.d.mts +11 -0
- package/dist/model/content/InlinePicture.mjs +21 -1
- package/dist/model/content/List.d.mts +6 -3
- package/dist/model/content/List.mjs +18 -8
- package/dist/model/content/Paragraph.d.mts +200 -14
- package/dist/model/content/Paragraph.mjs +898 -82
- package/dist/model/content/Range.d.mts +227 -12
- package/dist/model/content/Range.mjs +785 -59
- package/dist/model/content/ResolvedView.d.mts +104 -0
- package/dist/model/content/ResolvedView.mjs +596 -0
- package/dist/model/content/Table.d.mts +29 -3
- package/dist/model/content/Table.mjs +135 -49
- package/dist/model/content/TrackedChange.d.mts +174 -15
- package/dist/model/content/TrackedChange.mjs +734 -170
- package/dist/model/content/comments.d.mts +20 -6
- package/dist/model/content/comments.mjs +67 -57
- package/dist/model/content/generalException.d.mts +18 -0
- package/dist/model/content/generalException.mjs +24 -0
- package/dist/model/content/index.d.mts +10 -3
- package/dist/model/content/index.mjs +10 -2
- package/dist/model/content/mathText.d.mts +21 -0
- package/dist/model/content/mathText.mjs +267 -0
- package/dist/model/content/officeText.d.mts +27 -0
- package/dist/model/content/officeText.mjs +74 -0
- package/dist/model/content/ooxml.mjs +12 -1
- package/dist/model/content/outline.d.mts +5 -0
- package/dist/model/content/outline.mjs +13 -0
- package/dist/model/content/paraIds.d.mts +5 -0
- package/dist/model/content/paraIds.mjs +54 -0
- package/dist/model/content/placeholders.d.mts +110 -0
- package/dist/model/content/placeholders.mjs +253 -0
- package/dist/model/content/search.d.mts +74 -0
- package/dist/model/content/search.mjs +255 -9
- package/dist/model/content/spanEdits.d.mts +159 -0
- package/dist/model/content/spanEdits.mjs +728 -0
- package/dist/model/content/story.d.mts +47 -0
- package/dist/model/content/story.mjs +95 -0
- package/dist/model/content/tableColumns.d.mts +1 -1
- package/dist/model/content/tableColumns.mjs +108 -80
- package/dist/model/content/tableRevisions.d.mts +11 -3
- package/dist/model/content/tableRevisions.mjs +72 -42
- package/dist/model/content/tableRules.d.mts +30 -0
- package/dist/model/content/tableRules.mjs +102 -0
- package/dist/model/content/textBoxes.d.mts +18 -0
- package/dist/model/content/textBoxes.mjs +105 -0
- package/dist/model/content/trackedChangeFilter.d.mts +39 -0
- package/dist/model/content/trackedChangeFilter.mjs +81 -0
- package/dist/model/content/tracking.d.mts +63 -6
- package/dist/model/content/tracking.mjs +242 -22
- package/dist/model/content/tree.d.mts +172 -24
- package/dist/model/content/tree.mjs +328 -54
- package/dist/model/content/wordRange.d.mts +48 -0
- package/dist/model/content/wordRange.mjs +97 -0
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +30 -1
- package/dist/model/customxml/CustomXmlPartCollection.mjs +81 -12
- package/dist/model/customxml/XmlMapping.d.mts +32 -8
- package/dist/model/customxml/XmlMapping.mjs +64 -10
- package/dist/model/customxml/bindings.d.mts +33 -4
- package/dist/model/customxml/bindings.mjs +171 -45
- package/dist/model/customxml/index.d.mts +1 -0
- package/dist/model/customxml/index.mjs +1 -0
- package/dist/model/customxml/kinds.d.mts +8 -3
- package/dist/model/customxml/kinds.mjs +26 -5
- package/dist/model/customxml/opendope.d.mts +4 -1
- package/dist/model/customxml/opendope.mjs +9 -6
- package/dist/model/customxml/picturePlaceholder.d.mts +17 -0
- package/dist/model/customxml/picturePlaceholder.mjs +32 -0
- package/dist/model/customxml/pictures.d.mts +4 -3
- package/dist/model/customxml/pictures.mjs +22 -8
- package/dist/model/customxml/storeItems.d.mts +57 -0
- package/dist/model/customxml/storeItems.mjs +122 -0
- package/dist/model/customxml/xhtml.mjs +23 -22
- package/dist/model/dateZone.d.mts +25 -0
- package/dist/model/dateZone.mjs +57 -0
- package/dist/model/index.d.mts +3 -0
- package/dist/model/index.mjs +5 -0
- package/dist/model/listnumbering/Emulator.d.mts +37 -5
- package/dist/model/listnumbering/Emulator.mjs +63 -9
- package/dist/model/properties/PropertyResolver.d.mts +74 -2
- package/dist/model/properties/PropertyResolver.mjs +133 -5
- package/dist/model/properties/catalogue.d.mts +19 -5
- package/dist/model/properties/catalogue.mjs +41 -15
- package/dist/model/properties/index.d.mts +1 -1
- package/dist/model/properties/log.d.mts +1 -1
- package/dist/model/properties/log.mjs +5 -5
- package/dist/model/properties/styleUtil.d.mts +3 -1
- package/dist/model/properties/styleUtil.mjs +20 -24
- package/dist/model/properties/table.mjs +4 -2
- package/dist/model/text/CaseMapping.d.mts +38 -0
- package/dist/model/text/CaseMapping.mjs +86 -0
- package/dist/model/text/Extractor.d.mts +349 -0
- package/dist/model/text/Extractor.mjs +2406 -0
- package/dist/model/text/LinkTargets.d.mts +45 -0
- package/dist/model/text/LinkTargets.mjs +170 -0
- package/dist/model/text/MarkdownExporter.d.mts +140 -0
- package/dist/model/text/MarkdownExporter.mjs +255 -0
- package/dist/model/text/PlainText.d.mts +29 -0
- package/dist/model/text/PlainText.mjs +542 -0
- package/dist/model/text/TextContext.d.mts +256 -0
- package/dist/model/text/TextContext.mjs +600 -0
- package/dist/model/text/TextOptions.d.mts +233 -0
- package/dist/model/text/TextOptions.mjs +419 -0
- package/dist/model/text/TextResult.d.mts +621 -0
- package/dist/model/text/TextResult.mjs +629 -0
- package/dist/model/text/Texts.d.mts +99 -0
- package/dist/model/text/Texts.mjs +187 -0
- package/dist/model/text/WmlToMarkdown.d.mts +120 -0
- package/dist/model/text/WmlToMarkdown.mjs +936 -0
- package/dist/model/text/caseMapping.generated.d.mts +7 -0
- package/dist/model/text/caseMapping.generated.mjs +214 -0
- package/dist/model/text/commonmark.d.mts +121 -0
- package/dist/model/text/commonmark.mjs +655 -0
- package/dist/model/text/index.d.mts +8 -0
- package/dist/model/text/index.mjs +9 -0
- package/dist/model/text/normalize.d.mts +8 -0
- package/dist/model/text/normalize.mjs +13 -0
- package/dist/model/text/outline.d.mts +4 -0
- package/dist/model/text/outline.mjs +71 -0
- package/dist/model/wordIntegers.d.mts +29 -0
- package/dist/model/wordIntegers.mjs +78 -0
- package/dist/office-js/document.mjs +15 -1
- package/dist/office-js/fragment.d.mts +7 -5
- package/dist/office-js/fragment.mjs +63 -14
- package/dist/office-js/proxy.d.mts +8 -0
- package/dist/office-js/proxy.mjs +29 -0
- package/dist/office-js/run.mjs +2 -0
- package/dist/office-js/supported.generated.mjs +16 -0
- package/dist/office-js/toApiScript.mjs +29 -12
- package/dist/opc/DirectoryPartStore.d.mts +6 -2
- package/dist/opc/DirectoryPartStore.mjs +11 -4
- package/dist/opc/FlatOpcPartStore.d.mts +4 -2
- package/dist/opc/FlatOpcPartStore.mjs +11 -8
- package/dist/opc/Load.d.mts +32 -0
- package/dist/opc/Load.mjs +115 -5
- package/dist/opc/PartStore.d.mts +34 -1
- package/dist/opc/PartStore.mjs +71 -8
- package/dist/opc/Save.d.mts +32 -0
- package/dist/opc/Save.mjs +110 -4
- package/dist/opc/ZipPartStore.d.mts +4 -2
- package/dist/opc/ZipPartStore.mjs +12 -7
- package/dist/opc/exceptions.d.mts +140 -0
- package/dist/opc/exceptions.mjs +108 -0
- package/dist/opc/index.d.mts +8 -5
- package/dist/opc/index.mjs +5 -3
- package/dist/opc/mce/preprocessor.d.mts +141 -5
- package/dist/opc/mce/preprocessor.mjs +119 -18
- package/dist/opc/mce/understood.d.mts +3 -11
- package/dist/opc/mce/understood.mjs +27 -23
- package/dist/opc/repair/breaks.d.mts +23 -0
- package/dist/opc/repair/breaks.mjs +288 -0
- package/dist/opc/repair/hosts.d.mts +12 -0
- package/dist/opc/repair/hosts.mjs +33 -0
- package/dist/opc/repair/mainRoot.d.mts +19 -0
- package/dist/opc/repair/mainRoot.mjs +168 -0
- package/dist/opc/repair/unknownElements.d.mts +8 -0
- package/dist/opc/repair/unknownElements.mjs +180 -0
- package/dist/opc/repair/wmlNames.generated.d.mts +2 -0
- package/dist/opc/repair/wmlNames.generated.mjs +80 -0
- package/dist/opc/skipped.d.mts +50 -0
- package/dist/opc/skipped.mjs +140 -0
- package/dist/packages/OpcPackage.d.mts +110 -4
- package/dist/packages/OpcPackage.mjs +123 -7
- package/dist/packages/WordprocessingMLPackage.d.mts +45 -8
- package/dist/packages/WordprocessingMLPackage.mjs +158 -21
- package/dist/packages/index.d.mts +1 -1
- package/dist/parts/DefaultXmlPart.mjs +2 -2
- package/dist/parts/Part.d.mts +14 -2
- package/dist/parts/RelationshipsPart.d.mts +15 -0
- package/dist/parts/RelationshipsPart.mjs +66 -1
- package/dist/parts/XmlPart.d.mts +63 -32
- package/dist/parts/XmlPart.mjs +240 -96
- package/dist/parts/wml/comments.mjs +30 -0
- package/dist/parts/wml/index.d.mts +12 -1
- package/dist/parts/wml/index.mjs +37 -1
- package/dist/xml/dom.d.mts +7 -0
- package/dist/xml/dom.mjs +18 -0
- package/package.json +2 -2
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* docx4j `LinkTargets`. A target is written as a link when it has no scheme (a relative path, a fragment, a UNC
|
|
3
|
+
* path), is a Windows drive path (`C:\...`, `C:/...`), or its scheme is `http`, `https`, `ftp`, `mailto`, `file`,
|
|
4
|
+
* `news` or `tel`, or one the caller adds. docx4j adds them through its JVM-wide property
|
|
5
|
+
* `docx4j.convert.out.linkSchemes`; this package has no properties file, so they are an argument here and
|
|
6
|
+
* `MarkdownExportOptions.linkSchemes` on the export, for a deployment whose documents carry `onenote:`, `ms-word:` or
|
|
7
|
+
* `notes:` links. Added, never removed: a default stays.
|
|
8
|
+
*
|
|
9
|
+
* The scheme is read as a browser reads one (WHATWG URL parsing): leading control characters and spaces are ignored,
|
|
10
|
+
* and tabs and line breaks are dropped anywhere, so ` \u0001java\tscri\npt:` is `javascript:`; the comparison ignores
|
|
11
|
+
* case. Anything up to the first `:` (where that comes before any `/`, `?` or `#`) is the scheme, so a target whose
|
|
12
|
+
* scheme a browser would reject as malformed (`java script:`) is refused too, rather than second-guessed.
|
|
13
|
+
*/
|
|
14
|
+
export declare const LinkTargets: {
|
|
15
|
+
/** The default schemes, frozen. */
|
|
16
|
+
defaultSchemes(): readonly string[];
|
|
17
|
+
/**
|
|
18
|
+
* The schemes a link may use: the defaults plus `extra`, each trimmed and lower-cased, a trailing `:` dropped
|
|
19
|
+
* and an empty one ignored (docx4j reads its property's comma-separated list so).
|
|
20
|
+
*/
|
|
21
|
+
schemes(extra?: readonly string[]): readonly string[];
|
|
22
|
+
/**
|
|
23
|
+
* Whether an output may write this target as a link: it has no scheme, is a drive path, or its scheme (read as
|
|
24
|
+
* a browser reads it) is a default one or in `extra`. An undefined or empty target is safe (there is nothing to
|
|
25
|
+
* write).
|
|
26
|
+
*/
|
|
27
|
+
isSafe(target: string | undefined, extra?: readonly string[]): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* The target with its character references decoded as CommonMark decodes a link destination: a decimal (`:`) or
|
|
30
|
+
* hex (`:`) reference to its character, U+FFFD for zero, out of range or a surrogate; a named reference that
|
|
31
|
+
* stands for one ASCII character (`:`, `/`, `	`, ...) to that character. Other named references, and an
|
|
32
|
+
* `&` that begins no reference, stay as written. Decoded once, as a renderer decodes once. docx4j
|
|
33
|
+
* `decodeCharacterReferences`.
|
|
34
|
+
*/
|
|
35
|
+
decodeCharacterReferences(target: string | undefined): string | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* The target's scheme, read as a browser reads it, lower-cased; undefined where it has none (a relative path, a
|
|
38
|
+
* fragment, a UNC path, or nothing at all).
|
|
39
|
+
*/
|
|
40
|
+
scheme(target: string | undefined): string | undefined;
|
|
41
|
+
/** A target for a log line: at most 80 characters (UTF-16 units, as docx4j's), control characters shown as spaces. */
|
|
42
|
+
excerpt(target: string | undefined): string;
|
|
43
|
+
/** The message the export logs, once per document, when it refuses a target. */
|
|
44
|
+
refusedMessage(target: string | undefined): string;
|
|
45
|
+
};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// Which link targets the Markdown export writes as a link (CR-012 section 21, the port of docx4j CR-056 phase 1:
|
|
2
|
+
// `org.docx4j.convert.out.common.writer.LinkTargets`, docx4j 84ee9741c). A document's `w:hyperlink` relationship
|
|
3
|
+
// target or HYPERLINK field target was written as the link's destination as it is, so a crafted
|
|
4
|
+
// `javascript:alert(1)` target ran script in a page that rendered the Markdown as HTML (CWE-79, the defect
|
|
5
|
+
// apache/poi#1455 fixed in POI). The rule is docx4j's allowlist of schemes, read as written and with its character
|
|
6
|
+
// references decoded (docx4j's CR-056 section 14, CR-012 section 21.2 here); a refused target gives the link's text with
|
|
7
|
+
// no link.
|
|
8
|
+
/** docx4j's default schemes (POI's set). */
|
|
9
|
+
const DEFAULT_SCHEMES = Object.freeze(['http', 'https', 'ftp', 'mailto', 'file', 'news', 'tel']);
|
|
10
|
+
/**
|
|
11
|
+
* The HTML5 named character references that decode to an ASCII character. A scheme is ASCII, so these are the ones that
|
|
12
|
+
* can build one or end one (`:`, `/`, `#`, `?`, `	`, `
`); any other decodes to a
|
|
13
|
+
* character no scheme holds, or stays as written, and either way leaves a scheme malformed, which is refused.
|
|
14
|
+
*/
|
|
15
|
+
const ASCII_REFERENCES = Object.freeze({
|
|
16
|
+
Tab: '\t', NewLine: '\n', excl: '!', quot: '"', QUOT: '"', num: '#', dollar: '$', percnt: '%', amp: '&', AMP: '&',
|
|
17
|
+
apos: "'", lpar: '(', rpar: ')', ast: '*', midast: '*', plus: '+', comma: ',', period: '.', sol: '/', colon: ':',
|
|
18
|
+
semi: ';', lt: '<', LT: '<', equals: '=', gt: '>', GT: '>', quest: '?', commat: '@', lsqb: '[', lbrack: '[',
|
|
19
|
+
bsol: '\\', rsqb: ']', rbrack: ']', Hat: '^', lowbar: '_', UnderBar: '_', grave: '`', DiacriticalGrave: '`',
|
|
20
|
+
lcub: '{', lbrace: '{', verbar: '|', vert: '|', VerticalLine: '|', rcub: '}', rbrace: '}',
|
|
21
|
+
});
|
|
22
|
+
/** docx4j `isSafeAsWritten`, `isSafe` for one reading of the target: no scheme, a drive path, or an allowed scheme. */
|
|
23
|
+
function safeAsWritten(target, extra) {
|
|
24
|
+
const scheme = LinkTargets.scheme(target);
|
|
25
|
+
if (scheme === undefined)
|
|
26
|
+
return true;
|
|
27
|
+
if (scheme.length === 1 && /\p{L}/u.test(scheme)) {
|
|
28
|
+
// a Windows drive path, C:\ or C:/
|
|
29
|
+
const next = normalise(target).charAt(2);
|
|
30
|
+
return next === '\\' || next === '/';
|
|
31
|
+
}
|
|
32
|
+
return LinkTargets.schemes(extra).includes(scheme);
|
|
33
|
+
}
|
|
34
|
+
/** Leading controls and spaces removed; tabs and line breaks removed anywhere. */
|
|
35
|
+
function normalise(target) {
|
|
36
|
+
let out = '';
|
|
37
|
+
for (const c of target) {
|
|
38
|
+
if (c === '\t' || c === '\n' || c === '\r')
|
|
39
|
+
continue;
|
|
40
|
+
if (c <= ' ' && out.length === 0)
|
|
41
|
+
continue;
|
|
42
|
+
out += c;
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* docx4j `LinkTargets`. A target is written as a link when it has no scheme (a relative path, a fragment, a UNC
|
|
48
|
+
* path), is a Windows drive path (`C:\...`, `C:/...`), or its scheme is `http`, `https`, `ftp`, `mailto`, `file`,
|
|
49
|
+
* `news` or `tel`, or one the caller adds. docx4j adds them through its JVM-wide property
|
|
50
|
+
* `docx4j.convert.out.linkSchemes`; this package has no properties file, so they are an argument here and
|
|
51
|
+
* `MarkdownExportOptions.linkSchemes` on the export, for a deployment whose documents carry `onenote:`, `ms-word:` or
|
|
52
|
+
* `notes:` links. Added, never removed: a default stays.
|
|
53
|
+
*
|
|
54
|
+
* The scheme is read as a browser reads one (WHATWG URL parsing): leading control characters and spaces are ignored,
|
|
55
|
+
* and tabs and line breaks are dropped anywhere, so ` \u0001java\tscri\npt:` is `javascript:`; the comparison ignores
|
|
56
|
+
* case. Anything up to the first `:` (where that comes before any `/`, `?` or `#`) is the scheme, so a target whose
|
|
57
|
+
* scheme a browser would reject as malformed (`java script:`) is refused too, rather than second-guessed.
|
|
58
|
+
*/
|
|
59
|
+
export const LinkTargets = {
|
|
60
|
+
/** The default schemes, frozen. */
|
|
61
|
+
defaultSchemes() {
|
|
62
|
+
return DEFAULT_SCHEMES;
|
|
63
|
+
},
|
|
64
|
+
/**
|
|
65
|
+
* The schemes a link may use: the defaults plus `extra`, each trimmed and lower-cased, a trailing `:` dropped
|
|
66
|
+
* and an empty one ignored (docx4j reads its property's comma-separated list so).
|
|
67
|
+
*/
|
|
68
|
+
schemes(extra = []) {
|
|
69
|
+
const set = new Set(DEFAULT_SCHEMES);
|
|
70
|
+
for (const raw of extra) {
|
|
71
|
+
let s = raw.trim().toLowerCase();
|
|
72
|
+
if (s.endsWith(':'))
|
|
73
|
+
s = s.slice(0, -1);
|
|
74
|
+
if (s !== '')
|
|
75
|
+
set.add(s);
|
|
76
|
+
}
|
|
77
|
+
return [...set];
|
|
78
|
+
},
|
|
79
|
+
/**
|
|
80
|
+
* Whether an output may write this target as a link: it has no scheme, is a drive path, or its scheme (read as
|
|
81
|
+
* a browser reads it) is a default one or in `extra`. An undefined or empty target is safe (there is nothing to
|
|
82
|
+
* write).
|
|
83
|
+
*/
|
|
84
|
+
isSafe(target, extra = []) {
|
|
85
|
+
if (target === undefined || target === '')
|
|
86
|
+
return true;
|
|
87
|
+
if (!safeAsWritten(target, extra))
|
|
88
|
+
return false;
|
|
89
|
+
// as a CommonMark renderer reads a destination, its character references decoded (docx4j CR-056 section 14)
|
|
90
|
+
const decoded = LinkTargets.decodeCharacterReferences(target);
|
|
91
|
+
return decoded === target || safeAsWritten(decoded, extra);
|
|
92
|
+
},
|
|
93
|
+
/**
|
|
94
|
+
* The target with its character references decoded as CommonMark decodes a link destination: a decimal (`:`) or
|
|
95
|
+
* hex (`:`) reference to its character, U+FFFD for zero, out of range or a surrogate; a named reference that
|
|
96
|
+
* stands for one ASCII character (`:`, `/`, `	`, ...) to that character. Other named references, and an
|
|
97
|
+
* `&` that begins no reference, stay as written. Decoded once, as a renderer decodes once. docx4j
|
|
98
|
+
* `decodeCharacterReferences`.
|
|
99
|
+
*/
|
|
100
|
+
decodeCharacterReferences(target) {
|
|
101
|
+
if (target === undefined || !target.includes('&'))
|
|
102
|
+
return target;
|
|
103
|
+
let out = '';
|
|
104
|
+
let i = 0;
|
|
105
|
+
while (i < target.length) {
|
|
106
|
+
const c = target.charAt(i);
|
|
107
|
+
if (c !== '&') {
|
|
108
|
+
out += c;
|
|
109
|
+
i++;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const semi = target.indexOf(';', i);
|
|
113
|
+
if (semi < 0 || semi - i > 40) {
|
|
114
|
+
out += c;
|
|
115
|
+
i++;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const ref = target.substring(i + 1, semi);
|
|
119
|
+
let decoded;
|
|
120
|
+
if (ref.length > 1 && ref.charAt(0) === '#') {
|
|
121
|
+
const hex = ref.charAt(1) === 'x' || ref.charAt(1) === 'X';
|
|
122
|
+
const digits = ref.substring(hex ? 2 : 1);
|
|
123
|
+
if (digits !== '' && digits.length <= (hex ? 6 : 7) && (hex ? /^[0-9A-Fa-f]+$/ : /^[0-9]+$/).test(digits)) {
|
|
124
|
+
const cp = parseInt(digits, hex ? 16 : 10);
|
|
125
|
+
decoded = cp === 0 || cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff) ? '\ufffd' : String.fromCodePoint(cp);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
decoded = Object.prototype.hasOwnProperty.call(ASCII_REFERENCES, ref) ? ASCII_REFERENCES[ref] : undefined;
|
|
130
|
+
}
|
|
131
|
+
if (decoded === undefined) {
|
|
132
|
+
out += c;
|
|
133
|
+
i++;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
out += decoded;
|
|
137
|
+
i = semi + 1;
|
|
138
|
+
}
|
|
139
|
+
return out;
|
|
140
|
+
},
|
|
141
|
+
/**
|
|
142
|
+
* The target's scheme, read as a browser reads it, lower-cased; undefined where it has none (a relative path, a
|
|
143
|
+
* fragment, a UNC path, or nothing at all).
|
|
144
|
+
*/
|
|
145
|
+
scheme(target) {
|
|
146
|
+
if (target === undefined)
|
|
147
|
+
return undefined;
|
|
148
|
+
const s = normalise(target);
|
|
149
|
+
for (let i = 0; i < s.length; i++) {
|
|
150
|
+
const c = s.charAt(i);
|
|
151
|
+
if (c === ':')
|
|
152
|
+
return i === 0 ? undefined : s.slice(0, i).toLowerCase();
|
|
153
|
+
if (c === '/' || c === '?' || c === '#')
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
return undefined;
|
|
157
|
+
},
|
|
158
|
+
/** A target for a log line: at most 80 characters (UTF-16 units, as docx4j's), control characters shown as spaces. */
|
|
159
|
+
excerpt(target) {
|
|
160
|
+
if (target === undefined)
|
|
161
|
+
return 'undefined';
|
|
162
|
+
const s = target.length > 80 ? target.slice(0, 80) + '...' : target;
|
|
163
|
+
return s.replace(/[\u0000-\u001f]/g, ' ');
|
|
164
|
+
},
|
|
165
|
+
/** The message the export logs, once per document, when it refuses a target. */
|
|
166
|
+
refusedMessage(target) {
|
|
167
|
+
return 'Link target refused (scheme not in MarkdownExportOptions.linkSchemes): the text is written without a link: '
|
|
168
|
+
+ LinkTargets.excerpt(target);
|
|
169
|
+
},
|
|
170
|
+
};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { Part } from '../../parts/Part.mjs';
|
|
2
|
+
import { TextOptions, type TextOptionsInit, type TextModelView } from './TextOptions.mjs';
|
|
3
|
+
import { TextResult, type TextBlock, type TextRun } from './TextResult.mjs';
|
|
4
|
+
import type { TextPackage } from './TextContext.mjs';
|
|
5
|
+
/** A picture's image, for a `MarkdownExportOptions.imageDestination`. */
|
|
6
|
+
export interface MarkdownImage {
|
|
7
|
+
/** The picture's run in the block model. */
|
|
8
|
+
readonly run: TextRun;
|
|
9
|
+
/** The image part. */
|
|
10
|
+
readonly part: Part;
|
|
11
|
+
readonly bytes: Uint8Array;
|
|
12
|
+
readonly contentType: string;
|
|
13
|
+
/** The picture's number among the export's images with an image part, from 1. */
|
|
14
|
+
readonly index: number;
|
|
15
|
+
/** docx4j's file name for it, `image1.png`: `image`, the index, and the extension of its content type. */
|
|
16
|
+
readonly fileName: string;
|
|
17
|
+
}
|
|
18
|
+
/** Where a picture's Markdown image points: a data URI by default, or what a host makes of the image. */
|
|
19
|
+
export type MarkdownImageDestination = (image: MarkdownImage) => string | Promise<string>;
|
|
20
|
+
/** `MarkdownExportOptions.of`'s argument. */
|
|
21
|
+
export interface MarkdownExportOptionsInit {
|
|
22
|
+
/** The text model's options the export reads a package with; the default is the text model's. */
|
|
23
|
+
textOptions?: TextOptions | TextOptionsInit;
|
|
24
|
+
/** The view, which sets `textOptions.view`. */
|
|
25
|
+
view?: TextModelView;
|
|
26
|
+
/** Where each picture points; a data URI where unset. */
|
|
27
|
+
imageDestination?: MarkdownImageDestination;
|
|
28
|
+
/** Schemes a link may use beyond `LinkTargets`' defaults. */
|
|
29
|
+
linkSchemes?: readonly string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Options for `MarkdownExporter`. What text is written is the text model's, under its `TextOptions`
|
|
33
|
+
* (`textOptions`): the view, the stories, hidden text, field codes, metadata as YAML front matter, under the
|
|
34
|
+
* names of the WD's section 10. The options here are how it is written. docx4j `MarkdownExportOptions`.
|
|
35
|
+
*
|
|
36
|
+
* docx4j's `imageDirPath` and `imageTargetUri`, which write each image to a directory, are `imageDestination`
|
|
37
|
+
* here: nothing outside `./node` writes a file (CR-012 section 16.4). A host that wants the files writes
|
|
38
|
+
* them in the function, which is given docx4j's file name, and returns the link.
|
|
39
|
+
*/
|
|
40
|
+
export declare class MarkdownExportOptions {
|
|
41
|
+
/**
|
|
42
|
+
* The text model's options a package is read with (`MarkdownExporter.export(pkg)`): the default is the
|
|
43
|
+
* text model's, the `accepted` view, the main story with its text boxes and notes, hidden text left out.
|
|
44
|
+
* A result is written under the options it was read with.
|
|
45
|
+
*/
|
|
46
|
+
textOptions: TextOptions;
|
|
47
|
+
/** Where each picture points; a data URI (`data:image/png;base64,...`) where unset. */
|
|
48
|
+
imageDestination: MarkdownImageDestination | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Schemes a link may use beyond `LinkTargets`' defaults (`http`, `https`, `ftp`, `mailto`, `file`, `news`, `tel`),
|
|
51
|
+
* for documents that carry `onenote:` or `ms-word:` links. A link whose target has any other scheme is written as
|
|
52
|
+
* its text, with no link (docx4j CR-056, CR-012 section 21). docx4j's JVM-wide property
|
|
53
|
+
* `docx4j.convert.out.linkSchemes`; added to the defaults, never removing one.
|
|
54
|
+
*/
|
|
55
|
+
linkSchemes: readonly string[];
|
|
56
|
+
static of(init?: MarkdownExportOptionsInit | MarkdownExportOptions): MarkdownExportOptions;
|
|
57
|
+
/** The revision view: `accepted` (the default), `original` or `markup`. */
|
|
58
|
+
get view(): TextModelView;
|
|
59
|
+
set view(view: TextModelView);
|
|
60
|
+
}
|
|
61
|
+
/** A block's Markdown (`MarkdownExporter.blocks`). */
|
|
62
|
+
export interface MarkdownBlock {
|
|
63
|
+
readonly block: TextBlock;
|
|
64
|
+
/**
|
|
65
|
+
* Its Markdown: the lines from the start of the line its first character is on to the next block's, the
|
|
66
|
+
* blank line after it included. Empty for a block that writes nothing: an empty paragraph, or a code
|
|
67
|
+
* paragraph merged into the fence before it.
|
|
68
|
+
*/
|
|
69
|
+
readonly markdown: string;
|
|
70
|
+
}
|
|
71
|
+
/** A result's Markdown block by block (`MarkdownExporter.blocks`). */
|
|
72
|
+
export interface MarkdownBlocks {
|
|
73
|
+
/** The YAML front matter, under `metadata: true` (REQ-704); empty otherwise. */
|
|
74
|
+
readonly frontMatter: string;
|
|
75
|
+
/** Each block of the result, in its order, with its Markdown. */
|
|
76
|
+
readonly blocks: readonly MarkdownBlock[];
|
|
77
|
+
/** The whole: the front matter and the blocks' Markdown joined, what `export` gives. */
|
|
78
|
+
readonly markdown: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Exports WordprocessingML to Markdown, CommonMark with GFM's tables and strikethrough, footnotes and math
|
|
82
|
+
* (WD section 7.2). The text is the text model's (`Texts.of`, WD REQ-202): its block model is written as a
|
|
83
|
+
* Markdown tree, which a port of commonmark-java's Markdown renderer serializes, so the escaping and the list
|
|
84
|
+
* markers are commonmark-java's, and the Markdown docx4j's byte for byte.
|
|
85
|
+
*
|
|
86
|
+
* - a heading from its outline level, not its style's name; a list from its numbering, kept apart from an
|
|
87
|
+
* adjacent list and going on at Word's count after a paragraph that interrupts it (REQ-703);
|
|
88
|
+
* - bold, italic, struck-through and code text where a run adds them to its paragraph's style; a code-styled
|
|
89
|
+
* paragraph, or one in a mono paragraph style, a fenced code block;
|
|
90
|
+
* - links from a `w:hyperlink` or a HYPERLINK field, a target whose scheme isn't allowed (`javascript:`) written
|
|
91
|
+
* as its text with no link (`LinkTargets`, `linkSchemes`); pictures with the describer's text, their image a
|
|
92
|
+
* data URI unless `imageDestination` says otherwise;
|
|
93
|
+
* - notes `[^1]` and `[^e1]`, their definitions after the body; GFM tables, the header the `w:tblHeader` rows
|
|
94
|
+
* or the first row, a cell's paragraphs `<br>` apart; block quotes from the Quote styles;
|
|
95
|
+
* - in the `markup` view, CriticMarkup: `{++inserted++}`, `{--deleted--}` and `{>>comment<<}`;
|
|
96
|
+
* - under `metadata: true`, the document properties as YAML front matter (REQ-704).
|
|
97
|
+
*
|
|
98
|
+
* Async because a picture's bytes are read from its part. The package is not changed (REQ-204).
|
|
99
|
+
* docx4j `MarkdownExporter`.
|
|
100
|
+
*
|
|
101
|
+
* ```ts
|
|
102
|
+
* const md = await new MarkdownExporter().export(pkg);
|
|
103
|
+
* const result = await Texts.of(pkg, { view: 'markup' });
|
|
104
|
+
* PlainText.of(result); // the plain text and the Markdown of one reading
|
|
105
|
+
* await MarkdownExporter.export(result, pkg);
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export declare class MarkdownExporter {
|
|
109
|
+
readonly options: MarkdownExportOptions;
|
|
110
|
+
constructor(options?: MarkdownExportOptions | MarkdownExportOptionsInit);
|
|
111
|
+
/**
|
|
112
|
+
* The Markdown of a package (the text model's reading of it under `options.textOptions`), or of a result
|
|
113
|
+
* the text model has made, under the options it was read with: its view, and its metadata as front matter
|
|
114
|
+
* where it was read with `metadata: true`. A result's block quotes are nested by their indent beyond the
|
|
115
|
+
* quote style's own where the package it was read from is given, by their indent alone where it isn't.
|
|
116
|
+
*/
|
|
117
|
+
export(source: TextPackage | TextResult, pkg?: TextPackage): Promise<string>;
|
|
118
|
+
/**
|
|
119
|
+
* The Markdown of each block (CR-012 section 4.4, the editor's ask), the front matter apart: a host that
|
|
120
|
+
* writes something before each block, or stops after some, has the pieces `export` joins.
|
|
121
|
+
*/
|
|
122
|
+
blocks(source: TextPackage | TextResult, pkg?: TextPackage): Promise<MarkdownBlocks>;
|
|
123
|
+
/** `new MarkdownExporter().export(...)`. */
|
|
124
|
+
static export(source: TextPackage | TextResult, pkg?: TextPackage): Promise<string>;
|
|
125
|
+
/** `new MarkdownExporter().blocks(...)`. */
|
|
126
|
+
static blocks(source: TextPackage | TextResult, pkg?: TextPackage): Promise<MarkdownBlocks>;
|
|
127
|
+
/**
|
|
128
|
+
* The document properties as a YAML front-matter block (WD REQ-704, REQ-515): a mapping for each kind of
|
|
129
|
+
* property the package has, `core`, `app` and `custom`, in that order, each property by its element's
|
|
130
|
+
* local name (core, application) or its name (custom), its value a double-quoted string. Empty where the
|
|
131
|
+
* result's metadata has none.
|
|
132
|
+
*/
|
|
133
|
+
static frontMatter(result: TextResult): string;
|
|
134
|
+
/**
|
|
135
|
+
* A picture's destination: its image part's bytes (an SVG picture's SVG where it has no PNG copy, docx4j
|
|
136
|
+
* #699) as a data URI or as `imageDestination` says; empty where its image can't be had, so that its alt
|
|
137
|
+
* text is kept.
|
|
138
|
+
*/
|
|
139
|
+
private destination;
|
|
140
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { BinaryPart } from '../../parts/BinaryPart.mjs';
|
|
2
|
+
import { DefaultXmlPart } from '../../parts/DefaultXmlPart.mjs';
|
|
3
|
+
import { TextOptions } from './TextOptions.mjs';
|
|
4
|
+
import { TextResult } from './TextResult.mjs';
|
|
5
|
+
import { Texts } from './Texts.mjs';
|
|
6
|
+
import { WmlToMarkdown } from './WmlToMarkdown.mjs';
|
|
7
|
+
import { renderMarkdown } from './commonmark.mjs';
|
|
8
|
+
import { base64Encode } from '../../xml/dom.mjs';
|
|
9
|
+
const SVG = 'image/svg+xml';
|
|
10
|
+
/**
|
|
11
|
+
* Options for `MarkdownExporter`. What text is written is the text model's, under its `TextOptions`
|
|
12
|
+
* (`textOptions`): the view, the stories, hidden text, field codes, metadata as YAML front matter, under the
|
|
13
|
+
* names of the WD's section 10. The options here are how it is written. docx4j `MarkdownExportOptions`.
|
|
14
|
+
*
|
|
15
|
+
* docx4j's `imageDirPath` and `imageTargetUri`, which write each image to a directory, are `imageDestination`
|
|
16
|
+
* here: nothing outside `./node` writes a file (CR-012 section 16.4). A host that wants the files writes
|
|
17
|
+
* them in the function, which is given docx4j's file name, and returns the link.
|
|
18
|
+
*/
|
|
19
|
+
export class MarkdownExportOptions {
|
|
20
|
+
constructor() {
|
|
21
|
+
/**
|
|
22
|
+
* The text model's options a package is read with (`MarkdownExporter.export(pkg)`): the default is the
|
|
23
|
+
* text model's, the `accepted` view, the main story with its text boxes and notes, hidden text left out.
|
|
24
|
+
* A result is written under the options it was read with.
|
|
25
|
+
*/
|
|
26
|
+
this.textOptions = new TextOptions();
|
|
27
|
+
/**
|
|
28
|
+
* Schemes a link may use beyond `LinkTargets`' defaults (`http`, `https`, `ftp`, `mailto`, `file`, `news`, `tel`),
|
|
29
|
+
* for documents that carry `onenote:` or `ms-word:` links. A link whose target has any other scheme is written as
|
|
30
|
+
* its text, with no link (docx4j CR-056, CR-012 section 21). docx4j's JVM-wide property
|
|
31
|
+
* `docx4j.convert.out.linkSchemes`; added to the defaults, never removing one.
|
|
32
|
+
*/
|
|
33
|
+
this.linkSchemes = [];
|
|
34
|
+
}
|
|
35
|
+
static of(init) {
|
|
36
|
+
if (init instanceof MarkdownExportOptions)
|
|
37
|
+
return init;
|
|
38
|
+
const o = new MarkdownExportOptions();
|
|
39
|
+
if ((init === null || init === void 0 ? void 0 : init.textOptions) !== undefined)
|
|
40
|
+
o.textOptions = TextOptions.of(init.textOptions);
|
|
41
|
+
if ((init === null || init === void 0 ? void 0 : init.view) !== undefined)
|
|
42
|
+
o.view = init.view;
|
|
43
|
+
o.imageDestination = init === null || init === void 0 ? void 0 : init.imageDestination;
|
|
44
|
+
if ((init === null || init === void 0 ? void 0 : init.linkSchemes) !== undefined)
|
|
45
|
+
o.linkSchemes = [...init.linkSchemes];
|
|
46
|
+
return o;
|
|
47
|
+
}
|
|
48
|
+
/** The revision view: `accepted` (the default), `original` or `markup`. */
|
|
49
|
+
get view() {
|
|
50
|
+
return this.textOptions.view;
|
|
51
|
+
}
|
|
52
|
+
set view(view) {
|
|
53
|
+
this.textOptions.view = view;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Exports WordprocessingML to Markdown, CommonMark with GFM's tables and strikethrough, footnotes and math
|
|
58
|
+
* (WD section 7.2). The text is the text model's (`Texts.of`, WD REQ-202): its block model is written as a
|
|
59
|
+
* Markdown tree, which a port of commonmark-java's Markdown renderer serializes, so the escaping and the list
|
|
60
|
+
* markers are commonmark-java's, and the Markdown docx4j's byte for byte.
|
|
61
|
+
*
|
|
62
|
+
* - a heading from its outline level, not its style's name; a list from its numbering, kept apart from an
|
|
63
|
+
* adjacent list and going on at Word's count after a paragraph that interrupts it (REQ-703);
|
|
64
|
+
* - bold, italic, struck-through and code text where a run adds them to its paragraph's style; a code-styled
|
|
65
|
+
* paragraph, or one in a mono paragraph style, a fenced code block;
|
|
66
|
+
* - links from a `w:hyperlink` or a HYPERLINK field, a target whose scheme isn't allowed (`javascript:`) written
|
|
67
|
+
* as its text with no link (`LinkTargets`, `linkSchemes`); pictures with the describer's text, their image a
|
|
68
|
+
* data URI unless `imageDestination` says otherwise;
|
|
69
|
+
* - notes `[^1]` and `[^e1]`, their definitions after the body; GFM tables, the header the `w:tblHeader` rows
|
|
70
|
+
* or the first row, a cell's paragraphs `<br>` apart; block quotes from the Quote styles;
|
|
71
|
+
* - in the `markup` view, CriticMarkup: `{++inserted++}`, `{--deleted--}` and `{>>comment<<}`;
|
|
72
|
+
* - under `metadata: true`, the document properties as YAML front matter (REQ-704).
|
|
73
|
+
*
|
|
74
|
+
* Async because a picture's bytes are read from its part. The package is not changed (REQ-204).
|
|
75
|
+
* docx4j `MarkdownExporter`.
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* const md = await new MarkdownExporter().export(pkg);
|
|
79
|
+
* const result = await Texts.of(pkg, { view: 'markup' });
|
|
80
|
+
* PlainText.of(result); // the plain text and the Markdown of one reading
|
|
81
|
+
* await MarkdownExporter.export(result, pkg);
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export class MarkdownExporter {
|
|
85
|
+
constructor(options) {
|
|
86
|
+
this.options = MarkdownExportOptions.of(options);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The Markdown of a package (the text model's reading of it under `options.textOptions`), or of a result
|
|
90
|
+
* the text model has made, under the options it was read with: its view, and its metadata as front matter
|
|
91
|
+
* where it was read with `metadata: true`. A result's block quotes are nested by their indent beyond the
|
|
92
|
+
* quote style's own where the package it was read from is given, by their indent alone where it isn't.
|
|
93
|
+
*/
|
|
94
|
+
async export(source, pkg) {
|
|
95
|
+
return (await this.blocks(source, pkg)).markdown;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The Markdown of each block (CR-012 section 4.4, the editor's ask), the front matter apart: a host that
|
|
99
|
+
* writes something before each block, or stops after some, has the pieces `export` joins.
|
|
100
|
+
*/
|
|
101
|
+
async blocks(source, pkg) {
|
|
102
|
+
let result;
|
|
103
|
+
let styles;
|
|
104
|
+
if (source instanceof TextResult) {
|
|
105
|
+
result = source;
|
|
106
|
+
styles = pkg;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
result = await Texts.of(source, this.options.textOptions);
|
|
110
|
+
styles = source;
|
|
111
|
+
}
|
|
112
|
+
const writer = new WmlToMarkdown(result, await resolverOf(styles), this.options.linkSchemes);
|
|
113
|
+
const document = writer.convert();
|
|
114
|
+
let index = 0;
|
|
115
|
+
for (const { node, run } of writer.images) {
|
|
116
|
+
node.destination = await this.destination(run, () => ++index);
|
|
117
|
+
}
|
|
118
|
+
const starts = new Map();
|
|
119
|
+
const body = renderMarkdown(document, starts);
|
|
120
|
+
const frontMatter = result.options.metadata ? MarkdownExporter.frontMatter(result) : '';
|
|
121
|
+
return { frontMatter, blocks: sliced(result.blocks, starts, body), markdown: frontMatter + body };
|
|
122
|
+
}
|
|
123
|
+
/** `new MarkdownExporter().export(...)`. */
|
|
124
|
+
static async export(source, pkg) {
|
|
125
|
+
return new MarkdownExporter().export(source, pkg);
|
|
126
|
+
}
|
|
127
|
+
/** `new MarkdownExporter().blocks(...)`. */
|
|
128
|
+
static async blocks(source, pkg) {
|
|
129
|
+
return new MarkdownExporter().blocks(source, pkg);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* The document properties as a YAML front-matter block (WD REQ-704, REQ-515): a mapping for each kind of
|
|
133
|
+
* property the package has, `core`, `app` and `custom`, in that order, each property by its element's
|
|
134
|
+
* local name (core, application) or its name (custom), its value a double-quoted string. Empty where the
|
|
135
|
+
* result's metadata has none.
|
|
136
|
+
*/
|
|
137
|
+
static frontMatter(result) {
|
|
138
|
+
let sb = '';
|
|
139
|
+
for (const kind of [TextResult.CORE, TextResult.APP, TextResult.CUSTOM]) {
|
|
140
|
+
const properties = result.metadata[kind];
|
|
141
|
+
if (properties === null || typeof properties !== 'object')
|
|
142
|
+
continue;
|
|
143
|
+
const entries = properties instanceof Map ? [...properties.entries()] : Object.entries(properties);
|
|
144
|
+
if (entries.length === 0)
|
|
145
|
+
continue;
|
|
146
|
+
sb += `${kind}:\n`;
|
|
147
|
+
for (const [k, v] of entries)
|
|
148
|
+
sb += ` ${yamlKey(String(k))}: ${yamlString(String(v))}\n`;
|
|
149
|
+
}
|
|
150
|
+
return sb === '' ? '' : `---\n${sb}---\n\n`;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* A picture's destination: its image part's bytes (an SVG picture's SVG where it has no PNG copy, docx4j
|
|
154
|
+
* #699) as a data URI or as `imageDestination` says; empty where its image can't be had, so that its alt
|
|
155
|
+
* text is kept.
|
|
156
|
+
*/
|
|
157
|
+
async destination(run, next) {
|
|
158
|
+
var _a;
|
|
159
|
+
const part = (_a = run.image) === null || _a === void 0 ? void 0 : _a.part;
|
|
160
|
+
let bytes;
|
|
161
|
+
try {
|
|
162
|
+
if (part instanceof BinaryPart || (part instanceof DefaultXmlPart && part.contentType === SVG))
|
|
163
|
+
bytes = await part.getBytes();
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
bytes = undefined; // its alt text, with no destination
|
|
167
|
+
}
|
|
168
|
+
if (part === undefined || bytes === undefined)
|
|
169
|
+
return '';
|
|
170
|
+
const contentType = part.contentType;
|
|
171
|
+
if (this.options.imageDestination === undefined)
|
|
172
|
+
return `data:${contentType};base64,${base64Encode(bytes)}`;
|
|
173
|
+
const index = next();
|
|
174
|
+
return this.options.imageDestination({ run, part, bytes, contentType, index, fileName: `image${index}.${extensionFor(contentType, part)}` });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** The resolver a block quote's style indent is asked of: the package's, where it has a styles part. */
|
|
178
|
+
async function resolverOf(pkg) {
|
|
179
|
+
if (pkg === undefined)
|
|
180
|
+
return undefined;
|
|
181
|
+
try {
|
|
182
|
+
// asking a package with no styles part for a resolver would add one to it
|
|
183
|
+
if (!pkg.getMainDocumentPart().styleDefinitionsPart)
|
|
184
|
+
return undefined;
|
|
185
|
+
return await pkg.getPropertyResolver();
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/** Each block's Markdown: from its start to the next start, the last to the end; a start is one block's. */
|
|
192
|
+
function sliced(blocks, starts, body) {
|
|
193
|
+
const ordered = [...new Set(starts.values())].sort((a, b) => a - b);
|
|
194
|
+
const end = new Map();
|
|
195
|
+
ordered.forEach((s, i) => { var _a; return end.set(s, (_a = ordered[i + 1]) !== null && _a !== void 0 ? _a : body.length); });
|
|
196
|
+
const taken = new Set();
|
|
197
|
+
return blocks.map((block) => {
|
|
198
|
+
const start = starts.get(block);
|
|
199
|
+
if (start === undefined || taken.has(start))
|
|
200
|
+
return { block, markdown: '' };
|
|
201
|
+
taken.add(start);
|
|
202
|
+
return { block, markdown: body.slice(start, end.get(start)) };
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
function yamlKey(key) {
|
|
206
|
+
return /^[A-Za-z_][A-Za-z0-9_.-]*$/.test(key) ? key : yamlString(key);
|
|
207
|
+
}
|
|
208
|
+
/** A YAML double-quoted scalar: `\`, `"` and the control characters escaped. */
|
|
209
|
+
function yamlString(value) {
|
|
210
|
+
let sb = '"';
|
|
211
|
+
for (let i = 0; i < value.length; i++) {
|
|
212
|
+
const c = value.charAt(i);
|
|
213
|
+
const code = value.charCodeAt(i);
|
|
214
|
+
switch (c) {
|
|
215
|
+
case '"':
|
|
216
|
+
sb += '\\"';
|
|
217
|
+
break;
|
|
218
|
+
case '\\':
|
|
219
|
+
sb += '\\\\';
|
|
220
|
+
break;
|
|
221
|
+
case '\n':
|
|
222
|
+
sb += '\\n';
|
|
223
|
+
break;
|
|
224
|
+
case '\r':
|
|
225
|
+
sb += '\\r';
|
|
226
|
+
break;
|
|
227
|
+
case '\t':
|
|
228
|
+
sb += '\\t';
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
if (code < 0x20 || code === 0x7f || code === 0x85 || code === 0x2028 || code === 0x2029)
|
|
232
|
+
sb += `\\u${code.toString(16).padStart(4, '0')}`;
|
|
233
|
+
else
|
|
234
|
+
sb += c;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return `${sb}"`;
|
|
238
|
+
}
|
|
239
|
+
function extensionFor(contentType, part) {
|
|
240
|
+
switch (contentType) {
|
|
241
|
+
case 'image/png': return 'png';
|
|
242
|
+
case 'image/jpeg': return 'jpg';
|
|
243
|
+
case 'image/gif': return 'gif';
|
|
244
|
+
case 'image/bmp': return 'bmp';
|
|
245
|
+
case 'image/tiff': return 'tif';
|
|
246
|
+
case 'image/svg+xml': return 'svg';
|
|
247
|
+
case 'image/x-emf': return 'emf';
|
|
248
|
+
case 'image/x-wmf': return 'wmf';
|
|
249
|
+
default: {
|
|
250
|
+
const name = part.partName.name;
|
|
251
|
+
const dot = name.lastIndexOf('.');
|
|
252
|
+
return dot >= 0 ? name.substring(dot + 1) : 'bin';
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TextResult, TextBlock } from './TextResult.mjs';
|
|
2
|
+
/** The spaces for each 720-twip tab stop of indent under `layout: indent` (REQ-709). */
|
|
3
|
+
export declare const INDENT_SPACES = 4;
|
|
4
|
+
/** The note line before a table in the listed format (REQ-605, REQ-707). */
|
|
5
|
+
export declare const LISTED_FORMAT_NOTE = "[table: listed format]";
|
|
6
|
+
/**
|
|
7
|
+
* Plain text from the block model (WD section 7.1): each paragraph one line, a break one line more
|
|
8
|
+
* (REQ-603); the text exactly as the document holds it (REQ-602), U+000A between lines and after the last.
|
|
9
|
+
*
|
|
10
|
+
* Tables (REQ-605): a simple table a row a line, its cells a tab apart; any other in the listed format,
|
|
11
|
+
* after the note line `[table: listed format]`, a row a line as `Header: value; Header: value`. `tables:
|
|
12
|
+
* tsv` writes every table in the simple form, `tables: grid` as a pandoc grid table, its spans drawn.
|
|
13
|
+
*
|
|
14
|
+
* What the extractor adds follows the WD's bracket convention (REQ-707): `[n]` at a note's reference and
|
|
15
|
+
* at the start of the note; `[image: ...]` (or `[image, generated: ...]`) under `alt_text: true`; `[page
|
|
16
|
+
* n]` under `page_markers: true`; and under `metadata: true`, before the body, one line per kind of
|
|
17
|
+
* property that has any (REQ-515). In the markup view, insertions are `{++text++}`, deletions `{--text--}`
|
|
18
|
+
* and comments `{>>text<<}`, at their references with their replies after them (REQ-702, REQ-504); under
|
|
19
|
+
* `markup_detail` the marker's opening is followed by `author:` or `author, date:`.
|
|
20
|
+
*
|
|
21
|
+
* Under `layout: indent` (REQ-709) a paragraph outside a table begins with four spaces for each tab stop
|
|
22
|
+
* (720 twips) of its first line's indent, rounded to the nearest stop. docx4j `PlainText`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const PlainText: {
|
|
25
|
+
/** The plain text of a result. */
|
|
26
|
+
of(result: TextResult): string;
|
|
27
|
+
/** Whether a table is written in REQ-605's simple form under `tables: auto`. */
|
|
28
|
+
isSimple(table: TextBlock): boolean;
|
|
29
|
+
};
|