fix: import a list indented less than the level base
A list's own indent is the offset from the level's 1.27cm base, and the importers dropped it when the file put the list left of that (w:ind w:left="360" is a common one), so every item rendered 6.3mm too far right. The offset is signed now, floored at the base so the list stays inside the text column.
This commit is contained in:
1 parent
38e852190d
commit
8b9ba74a48
3 files changed
+12
-12
No files matched your search
@@ -110,14 +110,10 @@ function clampFirst(cm: number): number {
|
||||
return Math.round(Math.max(-INDENT_MAX_CM, Math.min(INDENT_MAX_CM, cm)) * 100) / 100;
|
||||
}
|
||||
|
||||
// Signed: a first-line indent may be negative (a hanging indent), and on a list the
|
||||
// value is the offset from the level's 1.27cm base, so a file whose list sits closer
|
||||
// to the margin than that imports a negative one.
|
||||
function parseIndent(value: string | null): number | null {
|
||||
if (value == null || value === '') return null;
|
||||
const n = parseFloat(value);
|
||||
return Number.isFinite(n) && n > 0 ? n : null;
|
||||
}
|
||||
|
||||
// A first-line indent may be negative (a hanging indent), unlike a left margin.
|
||||
function parseSignedIndent(value: string | null): number | null {
|
||||
if (value == null || value === '') return null;
|
||||
const n = parseFloat(value);
|
||||
return Number.isFinite(n) && n !== 0 ? n : null;
|
||||
@@ -171,7 +167,7 @@ export const Indent = Extension.create({
|
||||
// `indent`, which is the whole block's left margin.
|
||||
indentFirst: {
|
||||
default: null,
|
||||
parseHTML: (element: HTMLElement) => parseSignedIndent(element.getAttribute('data-indent-first')),
|
||||
parseHTML: (element: HTMLElement) => parseIndent(element.getAttribute('data-indent-first')),
|
||||
renderHTML: (attributes: Record<string, unknown>) => {
|
||||
if (attributes.indentFirst == null) return {};
|
||||
const cm = Number(attributes.indentFirst);
|
||||
|
||||
@@ -451,8 +451,10 @@ function makeListNode(ctx: Ctx, numId: number, ilvl: number): Node {
|
||||
if (def.start != null && def.start > 1) attrs.start = def.start;
|
||||
}
|
||||
if (ilvl === 0 && def.leftTwip != null) {
|
||||
const extra = round2(twipToCm(def.leftTwip) - LIST_LEFT_STEP_CM);
|
||||
if (extra > LIST_INDENT_EPS_CM) attrs.indent = extra;
|
||||
// Signed: a level's w:ind w:left may sit left of the editor's 1.27cm base
|
||||
// (w:left="360" is a common one). Floored there so the list stays in the text column.
|
||||
const extra = round2(Math.max(-LIST_LEFT_STEP_CM, twipToCm(def.leftTwip) - LIST_LEFT_STEP_CM));
|
||||
if (Math.abs(extra) > LIST_INDENT_EPS_CM) attrs.indent = extra;
|
||||
}
|
||||
const node: Node = { type: bullet ? 'bulletList' : 'orderedList', content: [] };
|
||||
if (Object.keys(attrs).length) node.attrs = attrs;
|
||||
|
||||
@@ -1355,8 +1355,10 @@ function convertList(el: Element, ctx: Ctx, inheritedStyleName: string | null, d
|
||||
if (depth === 1) {
|
||||
const mlCm = listLevelMarginLeftCm(levelDef);
|
||||
if (mlCm != null) {
|
||||
const extra = Math.round((mlCm - LIST_BASE_MARGIN_CM) * 100) / 100;
|
||||
if (extra > LIST_INDENT_EPS_CM) indent = extra;
|
||||
// Signed, floored at the base: a list may sit left of the editor's 1.27cm level
|
||||
// margin, but never left of the text column.
|
||||
const extra = Math.round(Math.max(-LIST_BASE_MARGIN_CM, mlCm - LIST_BASE_MARGIN_CM) * 100) / 100;
|
||||
if (Math.abs(extra) > LIST_INDENT_EPS_CM) indent = extra;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user