-
Notifications
You must be signed in to change notification settings - Fork 118
feat: add w:pPrChange translator for paragraph property tracked changes (SD-2417) #2705
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| // @ts-check | ||
| import { translator as mcAlternateContentTranslator } from '../../mc/altermateContent'; | ||
| import { translator as wAdjustRightIndTranslator } from '../adjustRightInd'; | ||
| import { translator as wAutoSpaceDETranslator } from '../autoSpaceDE'; | ||
| import { translator as wAutoSpaceDNTranslator } from '../autoSpaceDN'; | ||
| import { translator as wBidiTranslator } from '../bidi'; | ||
| import { translator as wCnfStyleTranslator } from '../cnfStyle'; | ||
| import { translator as wContextualSpacingTranslator } from '../contextualSpacing'; | ||
| import { translator as wDivIdTranslator } from '../divId'; | ||
| import { translator as wFramePrTranslator } from '../framePr'; | ||
| import { translator as wIndTranslator } from '../ind'; | ||
| import { translator as wJcTranslatorTranslator } from '../jc'; | ||
| import { translator as wKeepLinesTranslator } from '../keepLines'; | ||
| import { translator as wKeepNextTranslator } from '../keepNext'; | ||
| import { translator as wKinsokuTranslator } from '../kinsoku'; | ||
| import { translator as wMirrorIndentsTranslator } from '../mirrorIndents'; | ||
| import { translator as wNumPrTranslator } from '../numPr'; | ||
| import { translator as wOutlineLvlTranslator } from '../outlineLvl'; | ||
| import { translator as wOverflowPunctTranslator } from '../overflowPunct'; | ||
| import { translator as wPBdrTranslator } from '../pBdr'; | ||
| import { translator as wPStyleTranslator } from '../pStyle'; | ||
| import { translator as wPageBreakBeforeTranslator } from '../pageBreakBefore'; | ||
| import { translator as wShdTranslator } from '../shd'; | ||
| import { translator as wSnapToGridTranslator } from '../snapToGrid'; | ||
| import { translator as wSpacingTranslator } from '../spacing'; | ||
| import { translator as wSuppressAutoHyphensTranslator } from '../suppressAutoHyphens'; | ||
| import { translator as wSuppressLineNumbersTranslator } from '../suppressLineNumbers'; | ||
| import { translator as wSuppressOverlapTranslator } from '../suppressOverlap'; | ||
| import { translator as wTabsTranslator } from '../tabs'; | ||
| import { translator as wTextAlignmentTranslator } from '../textAlignment'; | ||
| import { translator as wTextDirectionTranslator } from '../textDirection'; | ||
| import { translator as wTextboxTightWrapTranslator } from '../textboxTightWrap'; | ||
| import { translator as wTopLinePunctTranslator } from '../topLinePunct'; | ||
| import { translator as wWidowControlTranslator } from '../widowControl'; | ||
| import { translator as wWordWrapTranslator } from '../wordWrap'; | ||
| import { translator as wRPrTranslator } from '../rpr'; | ||
|
|
||
| /** @type {import('@translator').NodeTranslator[]} */ | ||
| export const basePropertyTranslators = [ | ||
| mcAlternateContentTranslator, | ||
| wAdjustRightIndTranslator, | ||
| wAutoSpaceDETranslator, | ||
| wAutoSpaceDNTranslator, | ||
| wBidiTranslator, | ||
| wCnfStyleTranslator, | ||
| wContextualSpacingTranslator, | ||
| wDivIdTranslator, | ||
| wFramePrTranslator, | ||
| wIndTranslator, | ||
| wJcTranslatorTranslator, | ||
| wKeepLinesTranslator, | ||
| wKeepNextTranslator, | ||
| wKinsokuTranslator, | ||
| wMirrorIndentsTranslator, | ||
| wNumPrTranslator, | ||
| wOutlineLvlTranslator, | ||
| wOverflowPunctTranslator, | ||
| wPBdrTranslator, | ||
| wPStyleTranslator, | ||
| wPageBreakBeforeTranslator, | ||
| wShdTranslator, | ||
| wSnapToGridTranslator, | ||
| wSpacingTranslator, | ||
| wSuppressAutoHyphensTranslator, | ||
| wSuppressLineNumbersTranslator, | ||
| wSuppressOverlapTranslator, | ||
| wTabsTranslator, | ||
| wTextAlignmentTranslator, | ||
| wTextDirectionTranslator, | ||
| wTextboxTightWrapTranslator, | ||
| wTopLinePunctTranslator, | ||
| wWidowControlTranslator, | ||
| wWordWrapTranslator, | ||
| wRPrTranslator, | ||
| ]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,82 +1,11 @@ | ||
| // @ts-check | ||
| import { NodeTranslator } from '@translator'; | ||
| import { createNestedPropertiesTranslator } from '@converter/v3/handlers/utils.js'; | ||
| import { translator as mcAlternateContentTranslator } from '../../mc/altermateContent'; | ||
| import { translator as wAdjustRightIndTranslator } from '../adjustRightInd'; | ||
| import { translator as wAutoSpaceDETranslator } from '../autoSpaceDE'; | ||
| import { translator as wAutoSpaceDNTranslator } from '../autoSpaceDN'; | ||
| import { translator as wBidiTranslator } from '../bidi'; | ||
| import { translator as wCnfStyleTranslator } from '../cnfStyle'; | ||
| import { translator as wContextualSpacingTranslator } from '../contextualSpacing'; | ||
| import { translator as wDivIdTranslator } from '../divId'; | ||
| import { translator as wFramePrTranslator } from '../framePr'; | ||
| import { translator as wIndTranslator } from '../ind'; | ||
| import { translator as wJcTranslatorTranslator } from '../jc'; | ||
| import { translator as wKeepLinesTranslator } from '../keepLines'; | ||
| import { translator as wKeepNextTranslator } from '../keepNext'; | ||
| import { translator as wKinsokuTranslator } from '../kinsoku'; | ||
| import { translator as wMirrorIndentsTranslator } from '../mirrorIndents'; | ||
| import { translator as wNumPrTranslator } from '../numPr'; | ||
| import { translator as wOutlineLvlTranslator } from '../outlineLvl'; | ||
| import { translator as wOverflowPunctTranslator } from '../overflowPunct'; | ||
| import { translator as wPBdrTranslator } from '../pBdr'; | ||
| import { translator as wPStyleTranslator } from '../pStyle'; | ||
| import { translator as wPageBreakBeforeTranslator } from '../pageBreakBefore'; | ||
| import { translator as wShdTranslator } from '../shd'; | ||
| import { translator as wSnapToGridTranslator } from '../snapToGrid'; | ||
| import { translator as wSpacingTranslator } from '../spacing'; | ||
| import { translator as wSuppressAutoHyphensTranslator } from '../suppressAutoHyphens'; | ||
| import { translator as wSuppressLineNumbersTranslator } from '../suppressLineNumbers'; | ||
| import { translator as wSuppressOverlapTranslator } from '../suppressOverlap'; | ||
| import { translator as wTabsTranslator } from '../tabs'; | ||
| import { translator as wTextAlignmentTranslator } from '../textAlignment'; | ||
| import { translator as wTextDirectionTranslator } from '../textDirection'; | ||
| import { translator as wTextboxTightWrapTranslator } from '../textboxTightWrap'; | ||
| import { translator as wTopLinePunctTranslator } from '../topLinePunct'; | ||
| import { translator as wWidowControlTranslator } from '../widowControl'; | ||
| import { translator as wWordWrapTranslator } from '../wordWrap'; | ||
| import { translator as wRPrTranslator } from '../rpr'; | ||
| import { basePropertyTranslators } from './pPr-base-translators.js'; | ||
| import { translator as wPPrChangeTranslator } from '../pPrChange'; | ||
|
|
||
| // Property translators for w:pPr child elements | ||
| // Each translator handles a specific property of the paragraph properties | ||
| /** @type {import('@translator').NodeTranslator[]} */ | ||
| const propertyTranslators = [ | ||
| mcAlternateContentTranslator, | ||
| wAdjustRightIndTranslator, | ||
| wAutoSpaceDETranslator, | ||
| wAutoSpaceDNTranslator, | ||
| wBidiTranslator, | ||
| wCnfStyleTranslator, | ||
| wContextualSpacingTranslator, | ||
| wDivIdTranslator, | ||
| wFramePrTranslator, | ||
| wIndTranslator, | ||
| wJcTranslatorTranslator, | ||
| wKeepLinesTranslator, | ||
| wKeepNextTranslator, | ||
| wKinsokuTranslator, | ||
| wMirrorIndentsTranslator, | ||
| wNumPrTranslator, | ||
| wOutlineLvlTranslator, | ||
| wOverflowPunctTranslator, | ||
| wPBdrTranslator, | ||
| wPStyleTranslator, | ||
| wPageBreakBeforeTranslator, | ||
| wShdTranslator, | ||
| wSnapToGridTranslator, | ||
| wSpacingTranslator, | ||
| wSuppressAutoHyphensTranslator, | ||
| wSuppressLineNumbersTranslator, | ||
| wSuppressOverlapTranslator, | ||
| wTabsTranslator, | ||
| wTextAlignmentTranslator, | ||
| wTextDirectionTranslator, | ||
| wTextboxTightWrapTranslator, | ||
| wTopLinePunctTranslator, | ||
| wWidowControlTranslator, | ||
| wWordWrapTranslator, | ||
| wRPrTranslator, | ||
| ]; | ||
| const propertyTranslators = [...basePropertyTranslators, wPPrChangeTranslator]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not blocking, just a heads up: the spec expects |
||
|
|
||
| /** | ||
| * The NodeTranslator instance for the w:pPr element. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export * from './pPrChange-translator.js'; |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,99 @@ | ||||||
| import { NodeTranslator } from '@translator'; | ||||||
| import { carbonCopy } from '@core/utilities/carbonCopy.js'; | ||||||
| import { createNestedPropertiesTranslator, createAttributeHandler } from '@converter/v3/handlers/utils.js'; | ||||||
| import { basePropertyTranslators } from '../pPr/pPr-base-translators.js'; | ||||||
|
|
||||||
| const pPrTranslator = NodeTranslator.from( | ||||||
| createNestedPropertiesTranslator('w:pPr', 'paragraphProperties', basePropertyTranslators), | ||||||
| ); | ||||||
|
|
||||||
| const ATTRIBUTE_HANDLERS = [ | ||||||
| createAttributeHandler('w:id'), | ||||||
| createAttributeHandler('w:author'), | ||||||
| createAttributeHandler('w:date'), | ||||||
| ]; | ||||||
|
|
||||||
| function getSectPr(pPrNode) { | ||||||
| const sectPr = pPrNode?.elements?.find((el) => el.name === 'w:sectPr'); | ||||||
| return sectPr ? carbonCopy(sectPr) : undefined; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * The NodeTranslator instance for the w:pPrChange element. | ||||||
| * @type {import('@translator').NodeTranslator} | ||||||
| */ | ||||||
| export const translator = NodeTranslator.from({ | ||||||
| xmlName: 'w:pPrChange', | ||||||
| sdNodeOrKeyName: 'change', | ||||||
| type: NodeTranslator.translatorTypes.NODE, | ||||||
| attributes: ATTRIBUTE_HANDLERS, | ||||||
| encode: (params, encodedAttrs = {}) => { | ||||||
| const changeNode = params.nodes[0]; | ||||||
| const pPrNode = changeNode?.elements?.find((el) => el.name === 'w:pPr'); | ||||||
|
|
||||||
| let paragraphProperties = pPrNode ? pPrTranslator.encode({ ...params, nodes: [pPrNode] }) : undefined; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when the spec says
Suggested change
|
||||||
| const sectPr = getSectPr(pPrNode); | ||||||
| if (sectPr) { | ||||||
| paragraphProperties = { | ||||||
| ...(paragraphProperties || {}), | ||||||
| sectPr, | ||||||
| }; | ||||||
| } | ||||||
|
|
||||||
| const result = { | ||||||
| ...encodedAttrs, | ||||||
| ...(paragraphProperties ? { paragraphProperties } : {}), | ||||||
| }; | ||||||
|
|
||||||
| return Object.keys(result).length ? result : undefined; | ||||||
| }, | ||||||
| decode: function (params) { | ||||||
| const change = params.node?.attrs?.change; | ||||||
| if (!change || typeof change !== 'object') return undefined; | ||||||
|
|
||||||
| const decodedAttrs = this.decodeAttributes({ | ||||||
| node: { ...params.node, attrs: change }, | ||||||
| }); | ||||||
| const hasParagraphProperties = Object.prototype.hasOwnProperty.call(change, 'paragraphProperties'); | ||||||
| const paragraphProperties = hasParagraphProperties ? change.paragraphProperties : undefined; | ||||||
|
|
||||||
| let pPrNode = | ||||||
| paragraphProperties && typeof paragraphProperties === 'object' | ||||||
| ? pPrTranslator.decode({ | ||||||
| ...params, | ||||||
| node: { ...params.node, attrs: { paragraphProperties } }, | ||||||
| }) | ||||||
| : undefined; | ||||||
|
|
||||||
| const sectPr = paragraphProperties?.sectPr ? carbonCopy(paragraphProperties.sectPr) : undefined; | ||||||
| if (sectPr) { | ||||||
| if (!pPrNode) { | ||||||
| pPrNode = { | ||||||
| name: 'w:pPr', | ||||||
| type: 'element', | ||||||
| attributes: {}, | ||||||
| elements: [], | ||||||
| }; | ||||||
| } | ||||||
| pPrNode.elements = [...(pPrNode.elements || []), sectPr]; | ||||||
| } | ||||||
|
|
||||||
| if (!pPrNode && hasParagraphProperties) { | ||||||
| pPrNode = { | ||||||
| name: 'w:pPr', | ||||||
| type: 'element', | ||||||
| attributes: {}, | ||||||
| elements: [], | ||||||
| }; | ||||||
| } | ||||||
|
|
||||||
| if (!pPrNode && !Object.keys(decodedAttrs).length) return undefined; | ||||||
|
|
||||||
| return { | ||||||
| name: 'w:pPrChange', | ||||||
| type: 'element', | ||||||
| attributes: decodedAttrs, | ||||||
| elements: pPrNode ? [pPrNode] : [], | ||||||
| }; | ||||||
| }, | ||||||
| }); | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
emitWhenAttributesOnlyisn't used anywhere — the pPrChange translator handles this case with its own logic instead. worth removing so it doesn't sit here unused?