feat(parser): support table and TOC

This commit is contained in:
syy11cn 2022-05-30 15:21:36 +08:00
parent e90cc2b639
commit 6c6cfc3baf
4 changed files with 90 additions and 7 deletions

View File

@ -1,7 +1,7 @@
import type Token from 'markdown-it/lib/token'
import MarkdownIt from 'markdown-it'
import type { ISectionOptions, IStylesOptions, Table, TableOfContents } from 'docx'
import { AlignmentType, BorderStyle, Document, Footer, Header, LevelFormat, Packer, PageNumber, Paragraph, SectionType, TextRun, convertInchesToTwip } from 'docx'
import type { ISectionOptions, IStylesOptions, Table } from 'docx'
import { AlignmentType, BorderStyle, Document, Footer, Header, LevelFormat, Packer, PageNumber, Paragraph, SectionType, StyleLevel, TableOfContents, TextRun, convertInchesToTwip } from 'docx'
import type { IMarkdownReportConfig } from '@md-report/types'
import { StyleId } from '@md-report/types'
import { sliceParagraph, sliceSection } from './utils'
@ -27,7 +27,80 @@ export function parse(props: { markdown: string; config: IMarkdownReportConfig }
export function parseDocument(tokens: Token[], styles: IStylesOptions): Document {
// Variables.
let pos = 0
const sections: ISectionOptions[] = []
const sections: ISectionOptions[] = [{
properties: {
type: SectionType.NEXT_PAGE,
page: {
margin: {
top: convertInchesToTwip(1),
bottom: convertInchesToTwip(1),
left: convertInchesToTwip(1.25),
right: convertInchesToTwip(1.25),
},
},
},
headers: {
default: new Header({
children: [new Paragraph({
style: StyleId.header,
border: {
bottom: {
color: 'auto',
style: BorderStyle.SINGLE,
size: 6,
},
},
text: '111',
})],
}),
even: new Header({
children: [new Paragraph({
style: StyleId.header,
border: {
bottom: {
color: 'auto',
style: BorderStyle.SINGLE,
size: 6,
},
},
text: '222',
})],
}),
},
footers: {
default: new Footer({
children: [new Paragraph({
style: StyleId.footer,
children: [new TextRun({
children: [PageNumber.CURRENT],
})],
})],
}),
even: new Footer({
children: [new Paragraph({
style: StyleId.footer,
children: [new TextRun({
children: [PageNumber.CURRENT],
})],
})],
}),
},
children: [
new TableOfContents('TOC', {
stylesWithLevels: [
new StyleLevel(StyleId.h1, 1),
new StyleLevel(StyleId.h2, 2),
new StyleLevel(StyleId.h3, 3),
new StyleLevel(StyleId.h4, 4),
new StyleLevel(StyleId.h5, 5),
new StyleLevel(StyleId.h6, 6),
],
useAppliedParagraphOutlineLevel: true,
hyperlink: true,
headingStyleRange: '1-3',
}),
],
}]
// Split and parse sections.
while (pos < tokens.length) {
const { tokens: section, offset } = sliceSection(tokens.slice(pos))
@ -148,6 +221,9 @@ export function parseDocument(tokens: Token[], styles: IStylesOptions): Document
},
],
},
features: {
updateFields: true,
},
evenAndOddHeaderAndFooters: true,
styles,
sections,

View File

@ -9,7 +9,7 @@ import { sliceInlineText } from './utils'
export function parseInline(props: { tokens: Token[]; style?: StyleId; headingLevel?: number; isUL?: boolean; isOL?: boolean }): Paragraph {
// Props.
const { tokens, style = StyleId.normal, headingLevel = 0, isOL = false, isUL = false } = props
const { tokens, style = StyleId.p, headingLevel = 0, isOL = false, isUL = false } = props
const { children: childrenTokens, level } = tokens[0]
if (!childrenTokens)
return new Paragraph({})

View File

@ -1,6 +1,6 @@
import type Token from 'markdown-it/lib/token'
import type { IBorderOptions } from 'docx'
import { BorderStyle, Math, MathRun, Paragraph, Table, TableCell, TableRow, TextRun } from 'docx'
import { BorderStyle, Math, MathRun, Paragraph, Table, TableCell, TableRow, TextRun, WidthType } from 'docx'
import { StyleId } from '@md-report/types'
import { MathBlockRegExp, sliceTableRow } from './utils'
import { parseInline } from './inline'
@ -44,6 +44,10 @@ export function parseTable(tokens: Token[]): Table {
export function parseTableRow(tokens: Token[]): TableRow {
const cells: Token[] = tokens.filter(token => token.type === 'inline')
const children: TableCell[] = cells.map(cell => new TableCell({
width: {
size: 1 / cells.length,
type: WidthType.PERCENTAGE,
},
children: [parseInline({
tokens: [cell],
style: StyleId.table,

View File

@ -36,9 +36,12 @@ export function sliceParagraph(tokens: Token[]): SliceResult {
}
export function sliceTableRow(tokens: Token[]): SliceResult {
let offset = 0
while (tokens[offset]?.type !== 'tr_open')
let offset = 1
while (offset < tokens.length) {
if (tokens[offset].type === 'tr_open')
break
offset++
}
return {
tokens: tokens.slice(0, offset),
offset,