mirror of
https://github.com/docmost/docmost.git
synced 2026-08-25 04:02:15 +10:00
feat: proper DOCX support
This commit is contained in:
+1
-1
Submodule apps/server/src/ee updated: 05529bcf97...c7b77ffb9e
@@ -1,4 +1,4 @@
|
|||||||
import { HeadingLevel, ShadingType } from 'docx';
|
import { FootnoteReferenceRun, HeadingLevel, Paragraph, ShadingType } from 'docx';
|
||||||
import { Node } from 'prosemirror-model';
|
import { Node } from 'prosemirror-model';
|
||||||
import {
|
import {
|
||||||
DocxSerializerAsync,
|
DocxSerializerAsync,
|
||||||
@@ -169,15 +169,26 @@ export const defaultAsyncNodes: NodeSerializerAsync = {
|
|||||||
state.closeBlock(node, { pageBreakBefore: true });
|
state.closeBlock(node, { pageBreakBefore: true });
|
||||||
},
|
},
|
||||||
footnoteReference(state, node) {
|
footnoteReference(state, node) {
|
||||||
state.addRunOptions({ superScript: true });
|
const number =
|
||||||
state.text(`[${node.attrs?.referenceNumber ?? ''}]`);
|
Number(node.attrs?.referenceNumber) || state.$footnoteCounter + 1;
|
||||||
|
state.$footnoteCounter = Math.max(state.$footnoteCounter, number);
|
||||||
|
// seed an empty body so the reference stays valid even if the trailing
|
||||||
|
// footnotes list is missing; the footnotes node overwrites it with content
|
||||||
|
if (!state.footnotes[number]) {
|
||||||
|
state.footnotes[number] = { children: [new Paragraph('')] };
|
||||||
|
}
|
||||||
|
state.current.push(new FootnoteReferenceRun(number));
|
||||||
},
|
},
|
||||||
async footnotes(state, node) {
|
async footnotes(state, node) {
|
||||||
await state.renderList(node, 'numbered');
|
for (let i = 0; i < node.childCount; i += 1) {
|
||||||
},
|
const item = node.child(i);
|
||||||
async footnote(state, node) {
|
const number =
|
||||||
await state.renderListItem(node);
|
Number(String(item.attrs?.id ?? '').replace('fn:', '')) || i + 1;
|
||||||
|
await state.footnoteDefinition(item, number);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
// items are consumed by the footnotes handler above
|
||||||
|
footnote() {},
|
||||||
// No usable static export representation: skip without failing.
|
// No usable static export representation: skip without failing.
|
||||||
subpages() {},
|
subpages() {},
|
||||||
transclusionReference() {},
|
transclusionReference() {},
|
||||||
|
|||||||
@@ -824,6 +824,29 @@ export class DocxSerializerStateAsync {
|
|||||||
this.current.push(new FootnoteReferenceRun(this.$footnoteCounter));
|
this.current.push(new FootnoteReferenceRun(this.$footnoteCounter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fills the footnote body for an already-referenced footnote number from a
|
||||||
|
// node holding block content (Docmost keeps footnote text in a trailing
|
||||||
|
// list, separate from the inline reference).
|
||||||
|
async footnoteDefinition(node: Node, number: number) {
|
||||||
|
const { current, children, nextRunOpts, nextParentParagraphOpts } = this;
|
||||||
|
this.current = [];
|
||||||
|
this.children = [];
|
||||||
|
delete this.nextRunOpts;
|
||||||
|
delete this.nextParentParagraphOpts;
|
||||||
|
|
||||||
|
await this.renderContent(node);
|
||||||
|
this.footnotes[number] = {
|
||||||
|
children: this.children.filter(
|
||||||
|
(child): child is Paragraph => child instanceof Paragraph,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.current = current;
|
||||||
|
this.children = children;
|
||||||
|
this.nextRunOpts = nextRunOpts;
|
||||||
|
this.nextParentParagraphOpts = nextParentParagraphOpts;
|
||||||
|
}
|
||||||
|
|
||||||
closeBlock(node: Node, props?: IParagraphOptions) {
|
closeBlock(node: Node, props?: IParagraphOptions) {
|
||||||
const paragraph = new Paragraph({
|
const paragraph = new Paragraph({
|
||||||
children: this.current,
|
children: this.current,
|
||||||
|
|||||||
Reference in New Issue
Block a user