123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- import { getHorizontalAlign } from './align'
- import { getTextByPathList } from './utils'
- import {
- getFontType,
- getFontColor,
- getFontSize,
- getFontBold,
- getFontItalic,
- getFontDecoration,
- getFontDecorationLine,
- getFontSpace,
- getFontSubscript,
- getFontShadow
- } from './fontStyle'
- export function genTextBody(
- textBodyNode,
- spNode,
- slideLayoutSpNode,
- type,
- warpObj
- ) {
- if (!textBodyNode) return ''
- let text = ''
- const listCounters = {} // 添加列表计数器对象
- const slideMasterTextStyles = warpObj['slideMasterTextStyles']
- const pFontStyle = getTextByPathList(spNode, ['p:style', 'a:fontRef'])
- const pNode = textBodyNode['a:p']
- const pNodes = pNode.constructor === Array ? pNode : [pNode]
- let isList = ''
- for (const pNode of pNodes) {
- let rNode = pNode['a:r']
- let fldNode = pNode['a:fld']
- let brNode = pNode['a:br']
- if (rNode) {
- rNode = rNode.constructor === Array ? rNode : [rNode]
- if (fldNode) {
- fldNode = fldNode.constructor === Array ? fldNode : [fldNode]
- rNode = rNode.concat(fldNode)
- }
- if (brNode) {
- brNode = brNode.constructor === Array ? brNode : [brNode]
- brNode.forEach((item) => (item.type = 'br'))
- if (brNode.length > 1) brNode.shift()
- rNode = rNode.concat(brNode)
- rNode.sort((a, b) => {
- if (!a.attrs || !b.attrs) return true
- return a.attrs.order - b.attrs.order
- })
- }
- }
- const align = getHorizontalAlign(pNode, spNode, type, warpObj)
- const listType = getListType(pNode)
- if (listType) {
- const [tagName, className] = listType.split(' ')
- const level = parseInt(pNode['a:pPr'].attrs?.lvl || '0') // 获取列表层级
- const indentSize = (level + 1) * 20 // 根据层级计算缩进大小
- if (!isList) {
- text += `<${tagName} style="list-style: none; " class="${className}">`
- isList = listType
- listCounters[className] = 0
- }
- else if (isList && isList !== listType) {
- text += `</${isList.split(' ')[0]}>`
- text += `<${tagName} style="list-style: none; " class="${className}">`
- isList = listType
- listCounters[className] = 0
- }
- listCounters[className]++
- const currentNumber = listCounters[className]
- text += `<li style="text-align: ${align}; padding-left: ${indentSize}px;">`
- if (className === 'custom-bullet') {
- const bulletChar = pNode['a:pPr']['a:buChar'].attrs?.char || '•'
- const symbolMap = {
- 'n': '■', // 实心方块
- 'l': '●', // 实心圆
- 'u': '◆', // 实心菱形
- 'p': '□', // 空心方块
- 'ü': '✔', // 对号
- 'Ø': '➢', // 箭头
- '': '•' // 默认圆点
- }
- const displayChar = symbolMap[bulletChar] || bulletChar
- // 获取字体大小,与内容保持一致
- const fontSize = getFontSize(textBodyNode, slideLayoutSpNode, type, slideMasterTextStyles)
- const fontSizeStyle = fontSize ? `font-size: ${fontSize};` : ''
- text += `<span style="display: inline-block; width: 20px; ${fontSizeStyle}; margin-left: -20px;">${displayChar}</span>`
- }
- else {
- let displayNumber = ''
- switch (className) {
- case 'circle-number':
- const circleNums = ['①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩']
- displayNumber = circleNums[currentNumber - 1] || `${currentNumber}`
- break
- case 'roman-upper':
- const romanNums = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X']
- displayNumber = `${romanNums[currentNumber - 1]}.`
- break
- case 'alpha-upper':
- displayNumber = `${String.fromCharCode(64 + currentNumber)}.`
- break
- case 'alpha-lower-paren':
- displayNumber = `${String.fromCharCode(96 + currentNumber)})`
- break
- case 'alpha-lower':
- displayNumber = `${String.fromCharCode(96 + currentNumber)}.`
- break
- case 'chinese-upper': // 添加中文数字
- const chineseUpperNums = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
- displayNumber = `${chineseUpperNums[currentNumber - 1]}.`
- break
- default:
- displayNumber = `${currentNumber}.`
- }
- // 获取字体大小,与内容保持一致
- const fontSize = getFontSize(textBodyNode, slideLayoutSpNode, type, slideMasterTextStyles)
- const fontSizeStyle = fontSize ? `font-size: ${fontSize};` : ''
- text += `<span style="display: inline-block; ${fontSizeStyle}; margin-left: -20px;">${displayNumber}</span>`
- }
- }
- else {
- if (isList) {
- text += `</${isList.split(' ')[0]}>`
- isList = ''
- }
- text += `<p style="text-align: ${align};">`
- }
- if (!rNode) {
- text += genSpanElement(
- pNode,
- spNode,
- textBodyNode,
- pFontStyle,
- slideLayoutSpNode,
- type,
- warpObj
- )
- }
- else {
- for (const rNodeItem of rNode) {
- text += genSpanElement(
- rNodeItem,
- pNode,
- textBodyNode,
- pFontStyle,
- slideLayoutSpNode,
- type,
- warpObj
- )
- }
- }
- if (listType) text += '</li>'
- else text += '</p>'
- }
- return text
- }
- export function getListType(node) {
- const pPrNode = node['a:pPr']
- if (!pPrNode) return ''
- if (pPrNode['a:buChar']) {
- return 'ul custom-bullet'
- }
- if (pPrNode['a:buAutoNum']) {
- const numType = pPrNode['a:buAutoNum'].attrs?.type || 'arabicPeriod'
- // 根据不同的编号类型返回对应的样式
- switch (numType) {
- case 'circleNumDbPlain':
- return 'ol circle-number' // ①②③
- case 'romanUcPeriod':
- return 'ol roman-upper' // I. II. III.
- case 'alphaUcPeriod':
- return 'ol alpha-upper' // A. B. C.
- case 'alphaLcParen':
- return 'ol alpha-lower-paren' // a) b) c)
- case 'alphaLcPeriod':
- return 'ol alpha-lower' // a. b. c.
- case 'ea1JpnChsDbPeriod':
- return 'ol chinese-upper' // 一. 二. 三.
- default:
- return 'ol decimal' // 1. 2. 3.
- }
- }
- return ''
- }
- export function genSpanElement(
- node,
- pNode,
- textBodyNode,
- pFontStyle,
- slideLayoutSpNode,
- type,
- warpObj
- ) {
- const lstStyle = textBodyNode['a:lstStyle']
- const slideMasterTextStyles = warpObj['slideMasterTextStyles']
- let lvl = 1
- const pPrNode = pNode['a:pPr']
- if (pPrNode) {
- const lvlNode = getTextByPathList(pPrNode, ['attrs', 'lvl'])
- if (lvlNode !== undefined) lvl = parseInt(lvlNode) + 1
- }
- let fontSize
- const directSize = getTextByPathList(node, ['a:rPr', 'attrs', 'sz'])
- if (directSize) {
- // 如果节点本身有字体大小设置,直接使用
- fontSize = getFontSize(node, slideLayoutSpNode, type, slideMasterTextStyles)
- }
- else {
- // 如果节点没有字体大小设置,使用 textBodyNode
- fontSize = getFontSize(textBodyNode, slideLayoutSpNode, type, slideMasterTextStyles)
- }
- let text = node['a:t']
- if (typeof text !== 'string') text = getTextByPathList(node, ['a:fld', 'a:t'])
- if (typeof text !== 'string') text = ' '
- let styleText = ''
- const fontColor = getFontColor(
- node,
- pNode,
- lstStyle,
- pFontStyle,
- lvl,
- warpObj
- )
- const fontType = getFontType(node, type, warpObj)
- const fontBold = getFontBold(node)
- const fontItalic = getFontItalic(node)
- const fontDecoration = getFontDecoration(node)
- const fontDecorationLine = getFontDecorationLine(node)
- const fontSpace = getFontSpace(node)
- const shadow = getFontShadow(node, warpObj)
- const subscript = getFontSubscript(node)
- if (fontColor) styleText += `color: ${fontColor};`
- if (fontSize) styleText += `font-size: ${fontSize};`
- if (fontType) styleText += `font-family: ${fontType};`
- if (fontBold) styleText += `font-weight: ${fontBold};`
- if (fontItalic) styleText += `font-style: ${fontItalic};`
- if (fontDecoration) styleText += `text-decoration: ${fontDecoration};`
- if (fontDecorationLine) {
- styleText += `text-decoration-line: ${fontDecorationLine};`
- }
- if (fontSpace) styleText += `letter-spacing: ${fontSpace};`
- if (subscript) styleText += `vertical-align: ${subscript};`
- if (shadow) styleText += `text-shadow: ${shadow};`
- const linkID = getTextByPathList(node, [
- 'a:rPr',
- 'a:hlinkClick',
- 'attrs',
- 'r:id'
- ])
- if (linkID) {
- const linkURL = warpObj['slideResObj'][linkID]['target']
- return `<span style="${styleText}"><a href="${linkURL}" target="_blank">${text
- .replace(/\t/g, ' ')
- .replace(/\s/g, ' ')}</a></span>`
- }
- return `<span style="${styleText}">${text
- .replace(/\t/g, ' ')
- .replace(/\s/g, ' ')}</span>`
- }
|