mirror of https://gitee.com/godoos/godoos.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
6.0 KiB
241 lines
6.0 KiB
import Color from 'color'
|
|
import {
|
|
IElement,
|
|
ElementType,
|
|
TitleLevel,
|
|
ListStyle,
|
|
Command
|
|
} from '../../editor'
|
|
import {
|
|
Document,
|
|
Packer,
|
|
Paragraph,
|
|
Header,
|
|
Footer,
|
|
Table,
|
|
HeadingLevel,
|
|
ParagraphChild,
|
|
TextRun,
|
|
Tab,
|
|
ExternalHyperlink,
|
|
ImageRun,
|
|
WidthType,
|
|
TableRow,
|
|
TableCell,
|
|
MathRun
|
|
} from 'docx'
|
|
import { saveAs } from './utils'
|
|
|
|
// 标题映射
|
|
const titleLevelToHeadingLevel = {
|
|
[TitleLevel.FIRST]: HeadingLevel.HEADING_1,
|
|
[TitleLevel.SECOND]: HeadingLevel.HEADING_2,
|
|
[TitleLevel.THIRD]: HeadingLevel.HEADING_3,
|
|
[TitleLevel.FOURTH]: HeadingLevel.HEADING_4,
|
|
[TitleLevel.FIFTH]: HeadingLevel.HEADING_5,
|
|
[TitleLevel.SIXTH]: HeadingLevel.HEADING_6
|
|
}
|
|
|
|
function convertElementToParagraphChild(element: IElement): ParagraphChild {
|
|
if (element.type === ElementType.IMAGE) {
|
|
return new ImageRun({
|
|
type: 'png',
|
|
data: element.value,
|
|
transformation: {
|
|
width: element.width!,
|
|
height: element.height!
|
|
}
|
|
})
|
|
}
|
|
if (element.type === ElementType.HYPERLINK) {
|
|
return new ExternalHyperlink({
|
|
children: [
|
|
new TextRun({
|
|
text: element.valueList?.map(child => child.value).join(''),
|
|
style: 'Hyperlink'
|
|
})
|
|
],
|
|
link: element.url!
|
|
})
|
|
}
|
|
if (element.type === ElementType.TAB) {
|
|
return new TextRun({
|
|
children: [new Tab()]
|
|
})
|
|
}
|
|
if (element.type === ElementType.LATEX) {
|
|
return new MathRun(element.value)
|
|
}
|
|
return new TextRun({
|
|
font: element.font,
|
|
text: element.value,
|
|
bold: element.bold,
|
|
size: `${(element.size || 16) / 0.75}pt`,
|
|
color: Color(element.color).hex() || '#000000',
|
|
italics: element.italic,
|
|
strike: element.strikeout,
|
|
// highlight: element.highlight ? Color(element.highlight).hex() : undefined,
|
|
superScript: element.type === ElementType.SUPERSCRIPT,
|
|
subScript: element.type === ElementType.SUBSCRIPT,
|
|
underline: element.underline ? {} : undefined
|
|
})
|
|
}
|
|
|
|
type DocxChildren = (Paragraph | Table)[]
|
|
function convertElementListToDocxChildren(
|
|
elementList: IElement[]
|
|
): DocxChildren {
|
|
const children: DocxChildren = []
|
|
|
|
let paragraphChild: ParagraphChild[] = []
|
|
|
|
function appendParagraph() {
|
|
if (paragraphChild.length) {
|
|
children.push(
|
|
new Paragraph({
|
|
children: paragraphChild
|
|
})
|
|
)
|
|
paragraphChild = []
|
|
}
|
|
}
|
|
|
|
for (let e = 0; e < elementList.length; e++) {
|
|
const element = elementList[e]
|
|
if (element.type === ElementType.TITLE) {
|
|
appendParagraph()
|
|
children.push(
|
|
new Paragraph({
|
|
heading: titleLevelToHeadingLevel[element.level!],
|
|
children:
|
|
element.valueList?.map(child =>
|
|
convertElementToParagraphChild(child)
|
|
) || []
|
|
})
|
|
)
|
|
} else if (element.type === ElementType.LIST) {
|
|
appendParagraph()
|
|
// 拆分列表
|
|
const listChildren =
|
|
element.valueList
|
|
?.map(item => item.value)
|
|
.join('')
|
|
.split('\n')
|
|
.map(
|
|
(text, index) =>
|
|
new Paragraph({
|
|
children: [
|
|
new TextRun({
|
|
text: `${
|
|
!element.listStyle ||
|
|
element.listStyle === ListStyle.DECIMAL
|
|
? `${index + 1}. `
|
|
: `• `
|
|
}${text}`
|
|
})
|
|
]
|
|
})
|
|
) || []
|
|
children.push(...listChildren)
|
|
} else if (element.type === ElementType.TABLE) {
|
|
appendParagraph()
|
|
const { trList } = element
|
|
const tableRowList: TableRow[] = []
|
|
for (let r = 0; r < trList!.length; r++) {
|
|
const tdList = trList![r].tdList
|
|
const tableCellList: TableCell[] = []
|
|
for (let c = 0; c < tdList.length; c++) {
|
|
const td = tdList[c]
|
|
tableCellList.push(
|
|
new TableCell({
|
|
columnSpan: td.colspan,
|
|
rowSpan: td.rowspan,
|
|
children: convertElementListToDocxChildren(td.value) || []
|
|
})
|
|
)
|
|
}
|
|
tableRowList.push(
|
|
new TableRow({
|
|
children: tableCellList
|
|
})
|
|
)
|
|
}
|
|
children.push(
|
|
new Table({
|
|
rows: tableRowList,
|
|
width: {
|
|
size: '100%',
|
|
type: WidthType.PERCENTAGE
|
|
}
|
|
})
|
|
)
|
|
} else if (element.type === ElementType.DATE) {
|
|
paragraphChild.push(
|
|
...(element.valueList?.map(child =>
|
|
convertElementToParagraphChild(child)
|
|
) || [])
|
|
)
|
|
} else {
|
|
if (/^\n/.test(element.value)) {
|
|
appendParagraph()
|
|
element.value = element.value.replace(/^\n/, '')
|
|
}
|
|
paragraphChild.push(convertElementToParagraphChild(element))
|
|
}
|
|
}
|
|
appendParagraph()
|
|
return children
|
|
}
|
|
|
|
export interface IExportDocxOption {
|
|
fileName: string,
|
|
isFile:boolean
|
|
}
|
|
|
|
declare module '../../editor' {
|
|
interface Command {
|
|
executeExportDocx(options: IExportDocxOption): void
|
|
}
|
|
}
|
|
|
|
export default function (command: Command) {
|
|
return function (options: IExportDocxOption) {
|
|
const { fileName,isFile } = options
|
|
const {
|
|
data: { header, main, footer }
|
|
} = command.getValue()
|
|
|
|
const doc = new Document({
|
|
sections: [
|
|
{
|
|
headers: {
|
|
default: new Header({
|
|
children: convertElementListToDocxChildren(header || [])
|
|
})
|
|
},
|
|
footers: {
|
|
default: new Footer({
|
|
children: convertElementListToDocxChildren(footer || [])
|
|
})
|
|
},
|
|
children: convertElementListToDocxChildren(main || [])
|
|
}
|
|
]
|
|
})
|
|
if(isFile){
|
|
Packer.toBlob(doc).then(blob => {
|
|
saveAs(blob, `${fileName}`)
|
|
})
|
|
}else{
|
|
Packer.toBase64String(doc).then((base64:any) => {
|
|
const save = {
|
|
data: JSON.stringify({ content: base64, title: fileName }),
|
|
type: 'exportDocx'
|
|
}
|
|
//console.log(save)
|
|
window.parent.postMessage(save, '*')
|
|
})
|
|
}
|
|
|
|
}
|
|
}
|
|
|