@a3s-lab/office 0.30.0 → 0.31.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/README.md +22 -5
- package/dist/{0~7231.js → 0~4808.js} +189 -2
- package/dist/0~5050.js +10 -1
- package/dist/{0~7360.js → 0~7240.js} +244 -15
- package/dist/0~document-editor.js +622 -125
- package/dist/0~work-docx-export.js +214 -26
- package/dist/0~work-docx-import.js +17 -6
- package/dist/0~work-office-diagnostics.js +25 -4
- package/dist/4104.js +1 -1
- package/dist/4121.js +412 -11
- package/dist/6282.js +431 -2
- package/dist/internal/features/work/editors/document-command-catalog.d.ts +27 -0
- package/dist/internal/features/work/editors/document-dom-selection.d.ts +7 -0
- package/dist/internal/features/work/editors/document-editor-support.d.ts +1 -0
- package/dist/internal/features/work/editors/document-index-dialog.d.ts +10 -0
- package/dist/internal/features/work/editors/document-index-entry-dialog.d.ts +10 -0
- package/dist/internal/features/work/editors/document-references-ribbon.d.ts +19 -0
- package/dist/internal/features/work/editors/document-toolbar.d.ts +4 -1
- package/dist/internal/features/work/editors/use-document-insert-commands.d.ts +3 -0
- package/dist/internal/features/work/work-document-index-fields.d.ts +19 -0
- package/dist/internal/features/work/work-document-index-nodes.d.ts +32 -0
- package/dist/internal/features/work/work-document-index.d.ts +63 -0
- package/dist/internal/features/work/work-docx-import.d.ts +3 -1
- package/dist/internal/features/work/work-docx-index-export.d.ts +14 -0
- package/dist/internal/features/work/work-docx-index-import.d.ts +23 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +296 -0
- package/docs/latest/en/browser-editor-architecture.md +14 -0
- package/package.json +4 -1
package/dist/4121.js
CHANGED
|
@@ -1919,6 +1919,296 @@ function patchDocumentProofingLanguages(source, patch) {
|
|
|
1919
1919
|
function isRecord(source) {
|
|
1920
1920
|
return 'object' == typeof source && null !== source && !Array.isArray(source);
|
|
1921
1921
|
}
|
|
1922
|
+
const DEFAULT_DOCUMENT_INDEX_OPTIONS = {
|
|
1923
|
+
columns: 1,
|
|
1924
|
+
format: 'indented',
|
|
1925
|
+
rightAlignPageNumbers: true,
|
|
1926
|
+
leader: 'dot'
|
|
1927
|
+
};
|
|
1928
|
+
const MAX_DOCUMENT_INDEX_ENTRIES = 512;
|
|
1929
|
+
const MAX_DOCUMENT_INDEX_MARKERS = 2048;
|
|
1930
|
+
const MAX_DOCUMENT_INDEX_TERM_LENGTH = 240;
|
|
1931
|
+
const INDEX_ENTRY_SELECTOR = '[data-document-index-entry]';
|
|
1932
|
+
const INDEX_SELECTOR = '[data-document-index]';
|
|
1933
|
+
const INDEX_ID_PATTERN = /^[a-z0-9][a-z0-9._:-]{0,127}$/i;
|
|
1934
|
+
function normalizeDocumentIndexEntryDraft(source) {
|
|
1935
|
+
const mainEntry = normalizedIndexTerm(source?.mainEntry);
|
|
1936
|
+
if (!mainEntry) return null;
|
|
1937
|
+
const subEntry = normalizedIndexTerm(source?.subEntry);
|
|
1938
|
+
const crossReference = normalizedIndexTerm(source?.crossReference);
|
|
1939
|
+
return {
|
|
1940
|
+
mainEntry,
|
|
1941
|
+
subEntry,
|
|
1942
|
+
crossReference,
|
|
1943
|
+
pageBold: !crossReference && Boolean(source?.pageBold),
|
|
1944
|
+
pageItalic: !crossReference && Boolean(source?.pageItalic)
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1947
|
+
function normalizeDocumentIndexEntry(source, fallbackId = 'index-entry') {
|
|
1948
|
+
const value = normalizeDocumentIndexEntryDraft(source);
|
|
1949
|
+
if (!value) return null;
|
|
1950
|
+
return {
|
|
1951
|
+
id: validIndexId(source?.id) ?? fallbackId,
|
|
1952
|
+
...value
|
|
1953
|
+
};
|
|
1954
|
+
}
|
|
1955
|
+
function normalizeDocumentIndexOptions(source) {
|
|
1956
|
+
return {
|
|
1957
|
+
columns: boundedColumns(source?.columns),
|
|
1958
|
+
format: source?.format === 'run-in' ? 'run-in' : 'indented',
|
|
1959
|
+
rightAlignPageNumbers: source?.rightAlignPageNumbers !== false,
|
|
1960
|
+
leader: indexLeader(source?.leader) ?? 'dot'
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
function normalizeDocumentIndexValue(source) {
|
|
1964
|
+
return {
|
|
1965
|
+
id: validIndexId(source.id) ?? 'document-index',
|
|
1966
|
+
options: normalizeDocumentIndexOptions(source.options),
|
|
1967
|
+
entries: normalizeGeneratedEntries(source.entries),
|
|
1968
|
+
truncated: Boolean(source.truncated)
|
|
1969
|
+
};
|
|
1970
|
+
}
|
|
1971
|
+
function buildDocumentIndexEntries(document, options = {}) {
|
|
1972
|
+
const grouped = new Map();
|
|
1973
|
+
let markerCount = 0;
|
|
1974
|
+
document.descendants((node, position)=>{
|
|
1975
|
+
if ('documentIndexEntry' !== node.type.name) return;
|
|
1976
|
+
markerCount += 1;
|
|
1977
|
+
if (markerCount > MAX_DOCUMENT_INDEX_MARKERS) return;
|
|
1978
|
+
const marker = normalizeDocumentIndexEntry(node.attrs, `index-entry-${markerCount}`);
|
|
1979
|
+
if (!marker) return;
|
|
1980
|
+
const key = indexEntryKey(marker);
|
|
1981
|
+
let group = grouped.get(key);
|
|
1982
|
+
if (!group) {
|
|
1983
|
+
group = {
|
|
1984
|
+
entry: {
|
|
1985
|
+
mainEntry: marker.mainEntry,
|
|
1986
|
+
subEntry: marker.subEntry,
|
|
1987
|
+
crossReference: marker.crossReference,
|
|
1988
|
+
pages: []
|
|
1989
|
+
},
|
|
1990
|
+
pages: new Map()
|
|
1991
|
+
};
|
|
1992
|
+
grouped.set(key, group);
|
|
1993
|
+
}
|
|
1994
|
+
if (marker.crossReference) return;
|
|
1995
|
+
const pageNumber = positiveInteger(options.resolveContext?.(position)?.pageNumber) ?? fallbackDocumentPageNumber(document, position);
|
|
1996
|
+
const existing = group.pages.get(pageNumber);
|
|
1997
|
+
if (existing) {
|
|
1998
|
+
existing.pageBold ||= marker.pageBold;
|
|
1999
|
+
existing.pageItalic ||= marker.pageItalic;
|
|
2000
|
+
if (!existing.targetIds.includes(marker.id)) existing.targetIds.push(marker.id);
|
|
2001
|
+
return;
|
|
2002
|
+
}
|
|
2003
|
+
group.pages.set(pageNumber, {
|
|
2004
|
+
pageNumber,
|
|
2005
|
+
pageBold: marker.pageBold,
|
|
2006
|
+
pageItalic: marker.pageItalic,
|
|
2007
|
+
targetIds: [
|
|
2008
|
+
marker.id
|
|
2009
|
+
]
|
|
2010
|
+
});
|
|
2011
|
+
});
|
|
2012
|
+
const collator = new Intl.Collator(void 0, {
|
|
2013
|
+
numeric: true,
|
|
2014
|
+
sensitivity: 'base',
|
|
2015
|
+
usage: 'sort'
|
|
2016
|
+
});
|
|
2017
|
+
const allEntries = Array.from(grouped.values()).map(({ entry, pages })=>({
|
|
2018
|
+
...entry,
|
|
2019
|
+
pages: Array.from(pages.values()).sort((left, right)=>left.pageNumber - right.pageNumber)
|
|
2020
|
+
})).sort((left, right)=>collator.compare(left.mainEntry, right.mainEntry) || collator.compare(left.subEntry, right.subEntry) || collator.compare(left.crossReference, right.crossReference));
|
|
2021
|
+
return {
|
|
2022
|
+
entries: allEntries.slice(0, MAX_DOCUMENT_INDEX_ENTRIES),
|
|
2023
|
+
truncated: markerCount > MAX_DOCUMENT_INDEX_MARKERS || allEntries.length > MAX_DOCUMENT_INDEX_ENTRIES
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
2026
|
+
function documentIndexEntryHtml(source) {
|
|
2027
|
+
const value = normalizeDocumentIndexEntry(source);
|
|
2028
|
+
if (!value) return '';
|
|
2029
|
+
const detail = indexEntryDisplay(value);
|
|
2030
|
+
return [
|
|
2031
|
+
`<span data-document-index-entry="true" data-index-entry-id="${escapeHtmlAttribute(value.id)}" data-index-main-entry="${escapeHtmlAttribute(value.mainEntry)}" data-index-sub-entry="${escapeHtmlAttribute(value.subEntry)}" data-index-cross-reference="${escapeHtmlAttribute(value.crossReference)}" data-index-page-bold="${String(value.pageBold)}" data-index-page-italic="${String(value.pageItalic)}" class="work-document-index-entry" contenteditable="false" aria-label="索引项:${escapeHtmlAttribute(detail)}">`,
|
|
2032
|
+
'<span aria-hidden="true">索引项</span>',
|
|
2033
|
+
`<strong>${escapeHtml(detail)}</strong>`,
|
|
2034
|
+
'</span>'
|
|
2035
|
+
].join('');
|
|
2036
|
+
}
|
|
2037
|
+
function documentIndexHtml(source) {
|
|
2038
|
+
const value = normalizeDocumentIndexValue(source);
|
|
2039
|
+
const rows = value.entries.length ? value.entries.map(documentIndexRowHtml) : [
|
|
2040
|
+
'<li class="work-document-index-empty">没有已标记的索引项</li>'
|
|
2041
|
+
];
|
|
2042
|
+
const status = value.truncated ? `仅显示前 ${MAX_DOCUMENT_INDEX_ENTRIES} 项` : `${value.entries.length} 项`;
|
|
2043
|
+
return [
|
|
2044
|
+
`<div data-document-index="true" data-index-id="${escapeHtmlAttribute(value.id)}" data-index-columns="${value.options.columns}" data-index-format="${value.options.format}" data-index-right-align-page-numbers="${String(value.options.rightAlignPageNumbers)}" data-index-leader="${value.options.leader}" data-index-entries="${escapeHtmlAttribute(JSON.stringify(value.entries))}" data-index-truncated="${String(value.truncated)}" class="work-document-index" contenteditable="false" aria-label="索引">`,
|
|
2045
|
+
`<div class="work-document-index-header"><strong>索引</strong><span>${status}</span></div>`,
|
|
2046
|
+
'<ol class="work-document-index-list">',
|
|
2047
|
+
...rows,
|
|
2048
|
+
'</ol></div>'
|
|
2049
|
+
].join('');
|
|
2050
|
+
}
|
|
2051
|
+
function documentIndexEntryFromElement(element, index = 1) {
|
|
2052
|
+
return normalizeDocumentIndexEntry({
|
|
2053
|
+
id: element.dataset.indexEntryId,
|
|
2054
|
+
mainEntry: element.dataset.indexMainEntry,
|
|
2055
|
+
subEntry: element.dataset.indexSubEntry,
|
|
2056
|
+
crossReference: element.dataset.indexCrossReference,
|
|
2057
|
+
pageBold: 'true' === element.dataset.indexPageBold,
|
|
2058
|
+
pageItalic: 'true' === element.dataset.indexPageItalic
|
|
2059
|
+
}, `index-entry-${index}`);
|
|
2060
|
+
}
|
|
2061
|
+
function documentIndexValueFromElement(element, index = 1) {
|
|
2062
|
+
return normalizeDocumentIndexValue({
|
|
2063
|
+
id: validIndexId(element.dataset.indexId) ?? `document-index-${index}`,
|
|
2064
|
+
options: {
|
|
2065
|
+
columns: Number(element.dataset.indexColumns),
|
|
2066
|
+
format: 'run-in' === element.dataset.indexFormat ? 'run-in' : 'indented',
|
|
2067
|
+
rightAlignPageNumbers: 'false' !== element.dataset.indexRightAlignPageNumbers,
|
|
2068
|
+
leader: indexLeader(element.dataset.indexLeader) ?? 'dot'
|
|
2069
|
+
},
|
|
2070
|
+
entries: parseGeneratedEntries(element.dataset.indexEntries),
|
|
2071
|
+
truncated: 'true' === element.dataset.indexTruncated
|
|
2072
|
+
});
|
|
2073
|
+
}
|
|
2074
|
+
function normalizeDocumentIndexesHtml(source) {
|
|
2075
|
+
const document = new DOMParser().parseFromString(source, 'text/html');
|
|
2076
|
+
const usedEntryIds = new Set();
|
|
2077
|
+
for (const [index, element] of Array.from(document.body.querySelectorAll(INDEX_ENTRY_SELECTOR)).entries()){
|
|
2078
|
+
const value = documentIndexEntryFromElement(element, index + 1);
|
|
2079
|
+
if (!value) {
|
|
2080
|
+
element.remove();
|
|
2081
|
+
continue;
|
|
2082
|
+
}
|
|
2083
|
+
value.id = uniqueIndexId(value.id, 'index-entry', index + 1, usedEntryIds);
|
|
2084
|
+
element.replaceWith(document.createRange().createContextualFragment(documentIndexEntryHtml(value)));
|
|
2085
|
+
}
|
|
2086
|
+
const usedIndexIds = new Set();
|
|
2087
|
+
for (const [index, element] of Array.from(document.body.querySelectorAll(INDEX_SELECTOR)).entries()){
|
|
2088
|
+
const value = documentIndexValueFromElement(element, index + 1);
|
|
2089
|
+
value.id = uniqueIndexId(value.id, 'document-index', index + 1, usedIndexIds);
|
|
2090
|
+
element.replaceWith(document.createRange().createContextualFragment(documentIndexHtml(value)));
|
|
2091
|
+
}
|
|
2092
|
+
return document.body.innerHTML;
|
|
2093
|
+
}
|
|
2094
|
+
function indexLeader(value) {
|
|
2095
|
+
return 'dot' === value || 'dash' === value || 'underline' === value || 'none' === value ? value : null;
|
|
2096
|
+
}
|
|
2097
|
+
function documentIndexRowHtml(entry) {
|
|
2098
|
+
const term = entry.subEntry ? `<span class="work-document-index-main">${escapeHtml(entry.mainEntry)}</span><span class="work-document-index-sub">${escapeHtml(entry.subEntry)}</span>` : `<span class="work-document-index-main">${escapeHtml(entry.mainEntry)}</span>`;
|
|
2099
|
+
const pages = entry.crossReference ? `<span class="work-document-index-cross-reference">参见 ${escapeHtml(entry.crossReference)}</span>` : entry.pages.map((page)=>{
|
|
2100
|
+
const target = page.targetIds[0] ?? '';
|
|
2101
|
+
const classes = [
|
|
2102
|
+
page.pageBold ? 'bold' : '',
|
|
2103
|
+
page.pageItalic ? 'italic' : ''
|
|
2104
|
+
].filter(Boolean).join(' ');
|
|
2105
|
+
return `<a href="#${escapeHtmlAttribute(target)}" data-index-target="${escapeHtmlAttribute(target)}" tabindex="-1"${classes ? ` class="${classes}"` : ''}>${page.pageNumber}</a>`;
|
|
2106
|
+
}).join('<span aria-hidden="true">, </span>');
|
|
2107
|
+
return `<li data-index-main-entry="${escapeHtmlAttribute(entry.mainEntry)}" data-index-sub-entry="${escapeHtmlAttribute(entry.subEntry)}">${term}<i aria-hidden="true"></i><span class="work-document-index-pages">${pages}</span></li>`;
|
|
2108
|
+
}
|
|
2109
|
+
function normalizeGeneratedEntries(source) {
|
|
2110
|
+
const entries = [];
|
|
2111
|
+
for (const item of source.slice(0, MAX_DOCUMENT_INDEX_ENTRIES)){
|
|
2112
|
+
if (!item || 'object' != typeof item) continue;
|
|
2113
|
+
const candidate = item;
|
|
2114
|
+
const draft = normalizeDocumentIndexEntryDraft({
|
|
2115
|
+
mainEntry: normalizedIndexTerm(candidate.mainEntry),
|
|
2116
|
+
subEntry: normalizedIndexTerm(candidate.subEntry),
|
|
2117
|
+
crossReference: normalizedIndexTerm(candidate.crossReference)
|
|
2118
|
+
});
|
|
2119
|
+
if (draft) entries.push({
|
|
2120
|
+
mainEntry: draft.mainEntry,
|
|
2121
|
+
subEntry: draft.subEntry,
|
|
2122
|
+
crossReference: draft.crossReference,
|
|
2123
|
+
pages: draft.crossReference ? [] : normalizeIndexPages(candidate.pages)
|
|
2124
|
+
});
|
|
2125
|
+
}
|
|
2126
|
+
return entries;
|
|
2127
|
+
}
|
|
2128
|
+
function normalizeIndexPages(source) {
|
|
2129
|
+
if (!Array.isArray(source)) return [];
|
|
2130
|
+
const pages = [];
|
|
2131
|
+
const seen = new Set();
|
|
2132
|
+
for (const item of source.slice(0, MAX_DOCUMENT_INDEX_MARKERS)){
|
|
2133
|
+
if (!item || 'object' != typeof item) continue;
|
|
2134
|
+
const candidate = item;
|
|
2135
|
+
const pageNumber = positiveInteger(candidate.pageNumber);
|
|
2136
|
+
if (!pageNumber || seen.has(pageNumber)) continue;
|
|
2137
|
+
const targetIds = Array.isArray(candidate.targetIds) ? candidate.targetIds.flatMap((value)=>validIndexId(value) ? [
|
|
2138
|
+
String(value)
|
|
2139
|
+
] : []).slice(0, 64) : [];
|
|
2140
|
+
if (targetIds.length) {
|
|
2141
|
+
seen.add(pageNumber);
|
|
2142
|
+
pages.push({
|
|
2143
|
+
pageNumber,
|
|
2144
|
+
pageBold: Boolean(candidate.pageBold),
|
|
2145
|
+
pageItalic: Boolean(candidate.pageItalic),
|
|
2146
|
+
targetIds
|
|
2147
|
+
});
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
return pages.sort((left, right)=>left.pageNumber - right.pageNumber);
|
|
2151
|
+
}
|
|
2152
|
+
function parseGeneratedEntries(source) {
|
|
2153
|
+
if (!source) return [];
|
|
2154
|
+
try {
|
|
2155
|
+
const parsed = JSON.parse(source);
|
|
2156
|
+
return Array.isArray(parsed) ? normalizeGeneratedEntries(parsed) : [];
|
|
2157
|
+
} catch {
|
|
2158
|
+
return [];
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
function fallbackDocumentPageNumber(document, position) {
|
|
2162
|
+
let pageNumber = 1;
|
|
2163
|
+
document.descendants((node, offset)=>{
|
|
2164
|
+
if (offset >= position) return false;
|
|
2165
|
+
if ('pageBreak' === node.type.name) pageNumber += 1;
|
|
2166
|
+
return true;
|
|
2167
|
+
});
|
|
2168
|
+
return pageNumber;
|
|
2169
|
+
}
|
|
2170
|
+
function indexEntryKey(entry) {
|
|
2171
|
+
return [
|
|
2172
|
+
entry.mainEntry,
|
|
2173
|
+
entry.subEntry,
|
|
2174
|
+
entry.crossReference
|
|
2175
|
+
].map((value)=>value.normalize('NFKC').toLocaleLowerCase()).join('\u0000');
|
|
2176
|
+
}
|
|
2177
|
+
function indexEntryDisplay(entry) {
|
|
2178
|
+
const term = entry.subEntry ? `${entry.mainEntry} › ${entry.subEntry}` : entry.mainEntry;
|
|
2179
|
+
return entry.crossReference ? `${term} · 参见 ${entry.crossReference}` : term;
|
|
2180
|
+
}
|
|
2181
|
+
function normalizedIndexTerm(value) {
|
|
2182
|
+
return 'string' == typeof value ? value.replace(/\s+/g, ' ').trim().slice(0, MAX_DOCUMENT_INDEX_TERM_LENGTH) : '';
|
|
2183
|
+
}
|
|
2184
|
+
function boundedColumns(value) {
|
|
2185
|
+
const number = Number(value);
|
|
2186
|
+
return Number.isInteger(number) && number >= 1 && number <= 4 ? number : 1;
|
|
2187
|
+
}
|
|
2188
|
+
function positiveInteger(value) {
|
|
2189
|
+
const number = Number(value);
|
|
2190
|
+
return Number.isSafeInteger(number) && number > 0 ? Math.min(999999, number) : null;
|
|
2191
|
+
}
|
|
2192
|
+
function validIndexId(value) {
|
|
2193
|
+
return 'string' == typeof value && INDEX_ID_PATTERN.test(value) ? value : null;
|
|
2194
|
+
}
|
|
2195
|
+
function uniqueIndexId(source, prefix, index, used) {
|
|
2196
|
+
if (!used.has(source)) {
|
|
2197
|
+
used.add(source);
|
|
2198
|
+
return source;
|
|
2199
|
+
}
|
|
2200
|
+
let suffix = index;
|
|
2201
|
+
while(used.has(`${prefix}-${suffix}`))suffix += 1;
|
|
2202
|
+
const id = `${prefix}-${suffix}`;
|
|
2203
|
+
used.add(id);
|
|
2204
|
+
return id;
|
|
2205
|
+
}
|
|
2206
|
+
function escapeHtml(value) {
|
|
2207
|
+
return value.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');
|
|
2208
|
+
}
|
|
2209
|
+
function escapeHtmlAttribute(value) {
|
|
2210
|
+
return escapeHtml(value).replaceAll('"', '"').replaceAll("'", ''');
|
|
2211
|
+
}
|
|
1922
2212
|
const DOCUMENT_PARAGRAPH_ID_ATTRIBUTE = 'data-office-paragraph-id';
|
|
1923
2213
|
const DOCUMENT_PARAGRAPH_TEXT_ID_ATTRIBUTE = 'data-office-paragraph-text-id';
|
|
1924
2214
|
const PARAGRAPH_ID_PATTERN = /^[0-9A-F]{8}$/;
|
|
@@ -2310,7 +2600,7 @@ function documentTableOfContentsHtml(source) {
|
|
|
2310
2600
|
];
|
|
2311
2601
|
const status = value.truncated ? `仅显示前 ${MAX_DOCUMENT_TABLE_OF_CONTENTS_ENTRIES} 项` : `${value.entries.length} 项`;
|
|
2312
2602
|
return [
|
|
2313
|
-
`<div data-document-table-of-contents="true" data-toc-id="${
|
|
2603
|
+
`<div data-document-table-of-contents="true" data-toc-id="${work_document_table_of_contents_escapeHtmlAttribute(value.id)}" data-toc-min-level="${options.minLevel}" data-toc-max-level="${options.maxLevel}" data-toc-hyperlinks="${String(options.hyperlinks)}" data-toc-show-page-numbers="${String(options.showPageNumbers)}" data-toc-right-align-page-numbers="${String(options.rightAlignPageNumbers)}" data-toc-leader="${options.leader}" data-toc-entries="${work_document_table_of_contents_escapeHtmlAttribute(JSON.stringify(value.entries))}" data-toc-truncated="${String(value.truncated)}" class="work-document-table-of-contents" contenteditable="false" aria-label="目录">`,
|
|
2314
2604
|
'<div class="work-document-table-of-contents-header"><strong>目录</strong>',
|
|
2315
2605
|
`<span>${status}</span></div>`,
|
|
2316
2606
|
'<ol class="work-document-table-of-contents-list">',
|
|
@@ -2434,10 +2724,10 @@ function tableOfContentsEntryFromOutline(document, item, resolveContext) {
|
|
|
2434
2724
|
targetId: item.id,
|
|
2435
2725
|
title: item.text.slice(0, MAX_TABLE_OF_CONTENTS_TITLE_LENGTH),
|
|
2436
2726
|
level: item.level,
|
|
2437
|
-
pageNumber:
|
|
2727
|
+
pageNumber: work_document_table_of_contents_positiveInteger(resolveContext?.(item.from)?.pageNumber) ?? work_document_table_of_contents_fallbackDocumentPageNumber(document, item.from)
|
|
2438
2728
|
};
|
|
2439
2729
|
}
|
|
2440
|
-
function
|
|
2730
|
+
function work_document_table_of_contents_fallbackDocumentPageNumber(document, position) {
|
|
2441
2731
|
let pageNumber = 1;
|
|
2442
2732
|
document.descendants((node, offset)=>{
|
|
2443
2733
|
if (offset >= position) return false;
|
|
@@ -2447,8 +2737,8 @@ function fallbackDocumentPageNumber(document, position) {
|
|
|
2447
2737
|
return pageNumber;
|
|
2448
2738
|
}
|
|
2449
2739
|
function tableOfContentsEntryHtml(entry, options) {
|
|
2450
|
-
const title =
|
|
2451
|
-
const targetId =
|
|
2740
|
+
const title = work_document_table_of_contents_escapeHtml(entry.title);
|
|
2741
|
+
const targetId = work_document_table_of_contents_escapeHtmlAttribute(entry.targetId);
|
|
2452
2742
|
const label = options.hyperlinks ? `<a href="#${targetId}" data-toc-target="${targetId}" tabindex="-1">${title}</a>` : `<span>${title}</span>`;
|
|
2453
2743
|
const page = options.showPageNumbers ? `<span class="work-document-table-of-contents-page">${entry.pageNumber}</span>` : '';
|
|
2454
2744
|
return `<li data-toc-target="${targetId}" data-toc-level="${entry.level}" style="--work-toc-level:${entry.level}">${label}<i aria-hidden="true"></i>${page}</li>`;
|
|
@@ -2470,7 +2760,7 @@ function normalizeTableOfContentsEntries(source) {
|
|
|
2470
2760
|
const targetId = 'string' == typeof candidate.targetId ? candidate.targetId.trim() : '';
|
|
2471
2761
|
const title = 'string' == typeof candidate.title ? candidate.title.replace(/\s+/g, ' ').trim() : '';
|
|
2472
2762
|
const level = boundedLevel(candidate.level, 0);
|
|
2473
|
-
const pageNumber =
|
|
2763
|
+
const pageNumber = work_document_table_of_contents_positiveInteger(candidate.pageNumber);
|
|
2474
2764
|
if (TABLE_OF_CONTENTS_TARGET_PATTERN.test(targetId) && title && level && pageNumber) entries.push({
|
|
2475
2765
|
targetId,
|
|
2476
2766
|
title: title.slice(0, MAX_TABLE_OF_CONTENTS_TITLE_LENGTH),
|
|
@@ -2499,7 +2789,7 @@ function boundedLevel(value, fallback) {
|
|
|
2499
2789
|
const number = Number(value);
|
|
2500
2790
|
return Number.isInteger(number) && number >= 1 && number <= 9 ? number : fallback;
|
|
2501
2791
|
}
|
|
2502
|
-
function
|
|
2792
|
+
function work_document_table_of_contents_positiveInteger(value) {
|
|
2503
2793
|
const number = Number(value);
|
|
2504
2794
|
return Number.isSafeInteger(number) && number > 0 ? Math.min(999999, number) : null;
|
|
2505
2795
|
}
|
|
@@ -2517,11 +2807,11 @@ function uniqueTableOfContentsId(source, index, usedIds) {
|
|
|
2517
2807
|
usedIds.add(id);
|
|
2518
2808
|
return id;
|
|
2519
2809
|
}
|
|
2520
|
-
function
|
|
2810
|
+
function work_document_table_of_contents_escapeHtml(value) {
|
|
2521
2811
|
return value.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');
|
|
2522
2812
|
}
|
|
2523
|
-
function
|
|
2524
|
-
return
|
|
2813
|
+
function work_document_table_of_contents_escapeHtmlAttribute(value) {
|
|
2814
|
+
return work_document_table_of_contents_escapeHtml(value).replaceAll('"', '"').replaceAll("'", ''');
|
|
2525
2815
|
}
|
|
2526
2816
|
const WORK_TEMPLATES = [
|
|
2527
2817
|
{
|
|
@@ -2545,6 +2835,13 @@ const WORK_TEMPLATES = [
|
|
|
2545
2835
|
description: '标题级别、超链接、页码、前导符与原生 DOCX 往返',
|
|
2546
2836
|
accent: '#315f9f'
|
|
2547
2837
|
},
|
|
2838
|
+
{
|
|
2839
|
+
id: 'document-index',
|
|
2840
|
+
kind: 'document',
|
|
2841
|
+
name: '原生索引',
|
|
2842
|
+
description: '主次索引项、交叉引用、页码样式与原生 DOCX 往返',
|
|
2843
|
+
accent: '#4d6398'
|
|
2844
|
+
},
|
|
2548
2845
|
{
|
|
2549
2846
|
id: 'text-effects',
|
|
2550
2847
|
kind: 'document',
|
|
@@ -2639,6 +2936,7 @@ function initialTitle(templateId, kind) {
|
|
|
2639
2936
|
const titles = {
|
|
2640
2937
|
'project-brief': '新项目方案',
|
|
2641
2938
|
'table-of-contents': '可更新目录示例',
|
|
2939
|
+
'document-index': '原生索引示例',
|
|
2642
2940
|
'text-effects': '文字效果示例',
|
|
2643
2941
|
'run-borders': '字符边框示例',
|
|
2644
2942
|
'run-shading': '字符底纹示例',
|
|
@@ -2703,6 +3001,109 @@ function contentForTemplate(templateId) {
|
|
|
2703
3001
|
'<p>导出 DOCX 后仍保留原生 TOC 域、缓存目录项、超链接和前导符。</p>'
|
|
2704
3002
|
].join('')
|
|
2705
3003
|
};
|
|
3004
|
+
if ('document-index' === templateId) return {
|
|
3005
|
+
type: 'document',
|
|
3006
|
+
pageSize: 'a4',
|
|
3007
|
+
html: [
|
|
3008
|
+
documentIndexHtml({
|
|
3009
|
+
id: 'playground-document-index',
|
|
3010
|
+
options: {
|
|
3011
|
+
columns: 2,
|
|
3012
|
+
format: 'indented',
|
|
3013
|
+
rightAlignPageNumbers: true,
|
|
3014
|
+
leader: 'dot'
|
|
3015
|
+
},
|
|
3016
|
+
entries: [
|
|
3017
|
+
{
|
|
3018
|
+
mainEntry: 'Architecture',
|
|
3019
|
+
subEntry: '',
|
|
3020
|
+
crossReference: '',
|
|
3021
|
+
pages: [
|
|
3022
|
+
{
|
|
3023
|
+
pageNumber: 1,
|
|
3024
|
+
pageBold: false,
|
|
3025
|
+
pageItalic: false,
|
|
3026
|
+
targetIds: [
|
|
3027
|
+
'index-entry-architecture'
|
|
3028
|
+
]
|
|
3029
|
+
}
|
|
3030
|
+
]
|
|
3031
|
+
},
|
|
3032
|
+
{
|
|
3033
|
+
mainEntry: 'Architecture',
|
|
3034
|
+
subEntry: 'Runtime',
|
|
3035
|
+
crossReference: '',
|
|
3036
|
+
pages: [
|
|
3037
|
+
{
|
|
3038
|
+
pageNumber: 1,
|
|
3039
|
+
pageBold: true,
|
|
3040
|
+
pageItalic: false,
|
|
3041
|
+
targetIds: [
|
|
3042
|
+
'index-entry-runtime'
|
|
3043
|
+
]
|
|
3044
|
+
}
|
|
3045
|
+
]
|
|
3046
|
+
},
|
|
3047
|
+
{
|
|
3048
|
+
mainEntry: 'Collaboration',
|
|
3049
|
+
subEntry: '',
|
|
3050
|
+
crossReference: 'Architecture',
|
|
3051
|
+
pages: []
|
|
3052
|
+
},
|
|
3053
|
+
{
|
|
3054
|
+
mainEntry: 'Performance',
|
|
3055
|
+
subEntry: '',
|
|
3056
|
+
crossReference: '',
|
|
3057
|
+
pages: [
|
|
3058
|
+
{
|
|
3059
|
+
pageNumber: 2,
|
|
3060
|
+
pageBold: false,
|
|
3061
|
+
pageItalic: true,
|
|
3062
|
+
targetIds: [
|
|
3063
|
+
'index-entry-performance'
|
|
3064
|
+
]
|
|
3065
|
+
}
|
|
3066
|
+
]
|
|
3067
|
+
}
|
|
3068
|
+
]
|
|
3069
|
+
}),
|
|
3070
|
+
'<h1>原生索引</h1>',
|
|
3071
|
+
`<p>选择正文后,从“引用 → 标记索引项”创建主索引项、次索引项或交叉引用。${documentIndexEntryHtml({
|
|
3072
|
+
id: 'index-entry-architecture',
|
|
3073
|
+
mainEntry: 'Architecture',
|
|
3074
|
+
subEntry: '',
|
|
3075
|
+
crossReference: '',
|
|
3076
|
+
pageBold: false,
|
|
3077
|
+
pageItalic: false
|
|
3078
|
+
})}</p>`,
|
|
3079
|
+
`<p>Runtime 项的页码使用粗体,并作为 Architecture 的次索引项。${documentIndexEntryHtml({
|
|
3080
|
+
id: 'index-entry-runtime',
|
|
3081
|
+
mainEntry: 'Architecture',
|
|
3082
|
+
subEntry: 'Runtime',
|
|
3083
|
+
crossReference: '',
|
|
3084
|
+
pageBold: true,
|
|
3085
|
+
pageItalic: false
|
|
3086
|
+
})}</p>`,
|
|
3087
|
+
`<p>Collaboration 使用“参见 Architecture”交叉引用,不生成当前页码。${documentIndexEntryHtml({
|
|
3088
|
+
id: 'index-entry-collaboration',
|
|
3089
|
+
mainEntry: 'Collaboration',
|
|
3090
|
+
subEntry: '',
|
|
3091
|
+
crossReference: 'Architecture',
|
|
3092
|
+
pageBold: false,
|
|
3093
|
+
pageItalic: false
|
|
3094
|
+
})}</p>`,
|
|
3095
|
+
'<hr class="work-page-break" data-page-break="true">',
|
|
3096
|
+
`<p>Performance 位于第二页,页码使用斜体。${documentIndexEntryHtml({
|
|
3097
|
+
id: 'index-entry-performance',
|
|
3098
|
+
mainEntry: 'Performance',
|
|
3099
|
+
subEntry: '',
|
|
3100
|
+
crossReference: '',
|
|
3101
|
+
pageBold: false,
|
|
3102
|
+
pageItalic: true
|
|
3103
|
+
})}</p>`,
|
|
3104
|
+
'<p>修改索引项后选择“更新索引”,再导出 DOCX 验证原生 XE 与 INDEX 域。</p>'
|
|
3105
|
+
].join('')
|
|
3106
|
+
};
|
|
2706
3107
|
if ('text-effects' === templateId) return {
|
|
2707
3108
|
type: 'document',
|
|
2708
3109
|
pageSize: 'a4',
|
|
@@ -3445,4 +3846,4 @@ new TextEncoder();
|
|
|
3445
3846
|
function isOfficeKernelSpreadsheetError(value) {
|
|
3446
3847
|
return 'string' == typeof value && spreadsheetErrors.has(value);
|
|
3447
3848
|
}
|
|
3448
|
-
export { DEFAULT_DOCUMENT_TABLE_OF_CONTENTS_OPTIONS, DOCUMENT_HIGHLIGHT_ATTRIBUTE, DOCUMENT_NO_PROOF_ATTRIBUTE, DOCUMENT_PARAGRAPH_BORDERS_ATTRIBUTE, DOCUMENT_PARAGRAPH_BORDER_EDGES, DOCUMENT_PARAGRAPH_BORDER_STYLES, DOCUMENT_PARAGRAPH_ID_ATTRIBUTE, DOCUMENT_PARAGRAPH_TEXT_ID_ATTRIBUTE, DOCUMENT_PROOFING_LANGUAGES_ATTRIBUTE, DOCUMENT_RUN_BORDER_ATTRIBUTE, DOCUMENT_RUN_BORDER_STYLES, DOCUMENT_RUN_SHADING_ATTRIBUTE, DOCUMENT_SCRIPT_FONTS_ATTRIBUTE, DOCUMENT_SCRIPT_FONT_SLOT_ATTRIBUTE, DocumentParagraphIdentity, DocxThemePatchCollector, OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, OoxmlPackage, WORK_TEMPLATES as officeTemplates, applyDocumentParagraphIdentityToElement, attribute, buildDocumentTableOfContentsEntries, bytesToDataUrl, childPath, collectWorkDocumentOutline, contentTypeForPart, createDocumentParagraphIdentity, createDocumentParagraphIdentityRegistry, createWorkArtifact as createArtifact, createWorkId as createOfficeId, cssDocumentFontFamily, currentWorkDocumentOutlineItem, decodeXmlBytes, descendants, directChild, directChildren, documentBorderPresentation, documentFontNameFromCssFamily, documentHasIntegrityFeature, documentHighlightCssColor, documentHighlightDomAttributes, documentHighlightForCssColor, documentHighlightFromDocxValue, documentHighlightFromElement, documentNoProofFromElement, documentParagraphBordersDomAttributes, documentParagraphIdentityFromElement, documentParagraphShadingDomAttributes, documentProofingDomAttributes, documentProofingLanguagesFromElement, documentRunBorderDomAttributes, documentRunBorderIsVisible, documentRunShadingDomAttributes, documentScriptFontDirectFamily, documentScriptFontFallbackSlots, documentScriptFontFamily, documentScriptFontFamilyForRendering, documentScriptFontSegments, documentScriptFontSlotFromElement, documentScriptFontSlotFromHint, documentScriptFontsDomAttributes, documentScriptFontsForAllText, documentScriptFontsFromElement, documentTableOfContentsHtml, documentTableOfContentsValueFromElement, firstDescendant, isDocumentParagraphArtBorderStyle, isOfficeKernelSpreadsheetError, normalizeCssColor, normalizeDocumentFontName, normalizeDocumentHighlight, normalizeDocumentLanguageTag, normalizeDocumentNoProof, normalizeDocumentParagraphBorder, normalizeDocumentParagraphBorders, normalizeDocumentParagraphId, normalizeDocumentParagraphIdentity, normalizeDocumentProofingLanguages, normalizeDocumentRunBorder, normalizeDocumentRunShading, normalizeDocumentScriptFontHint, normalizeDocumentScriptFontSlot, normalizeDocumentScriptFonts, normalizeDocumentTableOfContentsHtml, normalizeDocumentTableOfContentsOptions, normalizeDocumentTableOfContentsValue, normalizeDocumentThemeFont, parseDocumentParagraphBorders, parseDocumentParagraphBordersElement, parseDocumentParagraphShading, parseDocumentParagraphShadingElement, parseDocumentProofingLanguages, parseDocumentRunBorder, parseDocumentRunBorderElement, parseDocumentRunShading, parseDocumentRunShadingElement, parseDocumentScriptFonts, parseDocumentTableOfContentsInstruction, parseDocxThemeReference, parseXml, patchDocumentProofingLanguages, patchDocumentScriptFonts, patchDocxThemeReferences, primeDocumentIntegrityFeatures, resolvePartTarget, serializeDocumentParagraphBorders, serializeDocumentParagraphShading, serializeDocumentProofingLanguages, serializeDocumentRunBorder, serializeDocumentRunShading, serializeDocumentScriptFonts, serializeDocxThemeReference, serializeUtf8Xml, uniqueDocumentParagraphIdentity, visibleWorkDocumentOutlineItems, workDocumentOutlineLevel, work_document_paragraph_shading_DOCUMENT_PARAGRAPH_SHADING_PATTERNS, xmlContainsAnyElement, xmlNamespacePrefix };
|
|
3849
|
+
export { DEFAULT_DOCUMENT_INDEX_OPTIONS, DEFAULT_DOCUMENT_TABLE_OF_CONTENTS_OPTIONS, DOCUMENT_HIGHLIGHT_ATTRIBUTE, DOCUMENT_NO_PROOF_ATTRIBUTE, DOCUMENT_PARAGRAPH_BORDERS_ATTRIBUTE, DOCUMENT_PARAGRAPH_BORDER_EDGES, DOCUMENT_PARAGRAPH_BORDER_STYLES, DOCUMENT_PARAGRAPH_ID_ATTRIBUTE, DOCUMENT_PARAGRAPH_TEXT_ID_ATTRIBUTE, DOCUMENT_PROOFING_LANGUAGES_ATTRIBUTE, DOCUMENT_RUN_BORDER_ATTRIBUTE, DOCUMENT_RUN_BORDER_STYLES, DOCUMENT_RUN_SHADING_ATTRIBUTE, DOCUMENT_SCRIPT_FONTS_ATTRIBUTE, DOCUMENT_SCRIPT_FONT_SLOT_ATTRIBUTE, DocumentParagraphIdentity, DocxThemePatchCollector, OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, OoxmlPackage, WORK_TEMPLATES as officeTemplates, applyDocumentParagraphIdentityToElement, attribute, buildDocumentIndexEntries, buildDocumentTableOfContentsEntries, bytesToDataUrl, childPath, collectWorkDocumentOutline, contentTypeForPart, createDocumentParagraphIdentity, createDocumentParagraphIdentityRegistry, createWorkArtifact as createArtifact, createWorkId as createOfficeId, cssDocumentFontFamily, currentWorkDocumentOutlineItem, decodeXmlBytes, descendants, directChild, directChildren, documentBorderPresentation, documentFontNameFromCssFamily, documentHasIntegrityFeature, documentHighlightCssColor, documentHighlightDomAttributes, documentHighlightForCssColor, documentHighlightFromDocxValue, documentHighlightFromElement, documentIndexEntryFromElement, documentIndexEntryHtml, documentIndexHtml, documentIndexValueFromElement, documentNoProofFromElement, documentParagraphBordersDomAttributes, documentParagraphIdentityFromElement, documentParagraphShadingDomAttributes, documentProofingDomAttributes, documentProofingLanguagesFromElement, documentRunBorderDomAttributes, documentRunBorderIsVisible, documentRunShadingDomAttributes, documentScriptFontDirectFamily, documentScriptFontFallbackSlots, documentScriptFontFamily, documentScriptFontFamilyForRendering, documentScriptFontSegments, documentScriptFontSlotFromElement, documentScriptFontSlotFromHint, documentScriptFontsDomAttributes, documentScriptFontsForAllText, documentScriptFontsFromElement, documentTableOfContentsHtml, documentTableOfContentsValueFromElement, firstDescendant, isDocumentParagraphArtBorderStyle, isOfficeKernelSpreadsheetError, normalizeCssColor, normalizeDocumentFontName, normalizeDocumentHighlight, normalizeDocumentIndexEntry, normalizeDocumentIndexEntryDraft, normalizeDocumentIndexOptions, normalizeDocumentIndexValue, normalizeDocumentIndexesHtml, normalizeDocumentLanguageTag, normalizeDocumentNoProof, normalizeDocumentParagraphBorder, normalizeDocumentParagraphBorders, normalizeDocumentParagraphId, normalizeDocumentParagraphIdentity, normalizeDocumentProofingLanguages, normalizeDocumentRunBorder, normalizeDocumentRunShading, normalizeDocumentScriptFontHint, normalizeDocumentScriptFontSlot, normalizeDocumentScriptFonts, normalizeDocumentTableOfContentsHtml, normalizeDocumentTableOfContentsOptions, normalizeDocumentTableOfContentsValue, normalizeDocumentThemeFont, parseDocumentParagraphBorders, parseDocumentParagraphBordersElement, parseDocumentParagraphShading, parseDocumentParagraphShadingElement, parseDocumentProofingLanguages, parseDocumentRunBorder, parseDocumentRunBorderElement, parseDocumentRunShading, parseDocumentRunShadingElement, parseDocumentScriptFonts, parseDocumentTableOfContentsInstruction, parseDocxThemeReference, parseXml, patchDocumentProofingLanguages, patchDocumentScriptFonts, patchDocxThemeReferences, primeDocumentIntegrityFeatures, resolvePartTarget, serializeDocumentParagraphBorders, serializeDocumentParagraphShading, serializeDocumentProofingLanguages, serializeDocumentRunBorder, serializeDocumentRunShading, serializeDocumentScriptFonts, serializeDocxThemeReference, serializeUtf8Xml, uniqueDocumentParagraphIdentity, visibleWorkDocumentOutlineItems, workDocumentOutlineLevel, work_document_paragraph_shading_DOCUMENT_PARAGRAPH_SHADING_PATTERNS, xmlContainsAnyElement, xmlNamespacePrefix };
|