Test of 2 formatted markers within same Text node passes

This commit is contained in:
David Bruant 2025-05-08 15:09:20 +02:00
parent 0825243b41
commit 3793923c79
5 changed files with 69 additions and 32 deletions

View File

@ -1,6 +1,6 @@
import {ZipReader, ZipWriter, BlobReader, BlobWriter, TextReader, Uint8ArrayReader, TextWriter, Uint8ArrayWriter} from '@zip.js/zip.js';
import {parseXML, serializeToString, Node} from '../../DOMUtils.js'
import {parseXML, serializeToString} from '../../DOMUtils.js'
import {makeManifestFile, getManifestFileData} from '../manifest.js';
import prepareTemplateDOMTree from './prepareTemplateDOMTree.js';
@ -164,8 +164,3 @@ export default async function fillOdtTemplate(odtTemplate, data) {
return writer.close();
}

View File

@ -35,7 +35,6 @@ function findAllMatches(text, pattern) {
return results;
}
/**
*
* @param {Node} node1
@ -72,7 +71,6 @@ function getAncestors(node) {
return ancestors;
}
/**
* text position of a node relative to a text nodes within a container
*
@ -268,8 +266,6 @@ function removeNodesBetween(startBranch, endBranch, commonAncestor) {
}
}
/**
* Consolidate markers which are split among several Text nodes
*
@ -277,23 +273,33 @@ function removeNodesBetween(startBranch, endBranch, commonAncestor) {
*/
function consolidateMarkers(document){
// Perform a first pass to detect templating markers with formatting to remove it
const potentialMarkerContainers = [
const potentialMarkersContainers = [
...Array.from(document.getElementsByTagName('text:p')),
...Array.from(document.getElementsByTagName('text:h'))
]
for(const potentialMarkerContainer of potentialMarkerContainers) {
// Check if any template marker is split across multiple text nodes
// Get all text nodes within this container
for(const potentialMarkersContainer of potentialMarkersContainers) {
const consolidatedMarkers = []
/** @type {Text[]} */
const containerTextNodesInTreeOrder = [];
let containerTextNodesInTreeOrder = [];
function refreshContainerTextNodes(){
containerTextNodesInTreeOrder = []
traverse(potentialMarkersContainer, node => {
if(node.nodeType === Node.TEXT_NODE) {
containerTextNodesInTreeOrder.push(/** @type {Text} */(node))
}
})
}
refreshContainerTextNodes()
let fullText = ''
traverse(potentialMarkerContainer, node => {
if(node.nodeType === Node.TEXT_NODE) {
containerTextNodesInTreeOrder.push(/** @type {Text} */(node))
fullText = fullText + node.textContent
}
})
for(const node of containerTextNodesInTreeOrder){
fullText = fullText + node.textContent
}
// Check for each template marker
const positionedMarkers = [
@ -307,10 +313,11 @@ function consolidateMarkers(document){
console.log('positionedMarkers', positionedMarkers)
// If no markers found, skip this container
if(positionedMarkers.length >= 1) {
while(consolidatedMarkers.length < positionedMarkers.length) {
refreshContainerTextNodes()
// For each marker, check if it's contained within a single text node
for(const positionedMarker of positionedMarkers) {
for(const positionedMarker of positionedMarkers.slice(consolidatedMarkers.length)) {
console.log('positionedMarker', positionedMarker)
let markerStart = -1;
@ -342,9 +349,16 @@ function consolidateMarkers(document){
currentPos = nodeEnd;
}
/*if(!startNode){
throw new Error(`Could not find startNode for marker '${positionedMarker.marker}'`)
}*/
/*if(!endNode){
throw new Error(`Could not find endNode for marker '${positionedMarker.marker}'`)
}*/
// Check if marker spans multiple nodes
if(startNode !== endNode) {
console.log('startNode !== endNode')
const commonAncestor = findCommonAncestor(startNode, endNode);
// Calculate relative positions within the nodes
@ -364,8 +378,6 @@ function consolidateMarkers(document){
// Find the diverging point in the paths
const lowestCommonAncestorChild = findDivergingPoint(pathToStart, pathToEnd);
console.log('lowestCommonAncestorChild', lowestCommonAncestorChild)
if(!lowestCommonAncestorChild) {
// Direct parent-child relationship or other simple case
// Handle separately
@ -392,6 +404,8 @@ function consolidateMarkers(document){
// Create a new node for the start of the marker
const startOfMarkerNode = document.createTextNode(positionedMarker.marker);
console.log('parentOfStartNode', parentOfStartNode)
// Insert after the modified start node
if(startNode.nextSibling) {
parentOfStartNode.insertBefore(startOfMarkerNode, startNode.nextSibling);
@ -437,15 +451,18 @@ function consolidateMarkers(document){
removeNodesBetween(startBranch, endBranch, commonAncestor);
}
// After consolidation, we can break as the DOM structure has changed
// After consolidation, break as the DOM structure has changed
// and containerTextNodesInTreeOrder needs to be refreshed
consolidatedMarkers.push(positionedMarker)
break;
}
consolidatedMarkers.push(positionedMarker)
}
}
}
}
/**
* isolate markers which are in Text nodes with other texts
*
@ -529,8 +546,6 @@ function isolateMarkers(document){
})
}
/**
* This function prepares the template DOM tree in a way that makes it easily processed by the template execution
* Specifically, after the call to this function, the document is altered to respect the following property:

View File

@ -5,8 +5,8 @@ import {getOdtTemplate} from '../../scripts/odf/odtTemplate-forNode.js'
import {fillOdtTemplate, getOdtTextContent} from '../../exports.js'
test('template filling {#each ...}{/each} with formating in {#each ...} start marker', async t => {
const templatePath = join(import.meta.dirname, '../fixtures/liste-nombres-avec-formattage.odt')
test('template filling with several layers of formatting in {#each ...} start marker', async t => {
const templatePath = join(import.meta.dirname, '../fixtures/formatting-liste-nombres-plusieurs-couches.odt')
const templateContent = `Liste de nombres
Les nombres : {#each nombres as n}{n} {/each} !!
@ -29,4 +29,31 @@ Les nombres : {#each nombres as n}{n} {/each} !!
Les nombres : 1 2 3 5  !!
`)
});
test('template filling - both {#each ...} and {/each} within the same Text node are formatted', async t => {
const templatePath = join(import.meta.dirname, '../fixtures/formatting-liste-nombres-2-markeurs-formatted.odt')
const templateContent = `Liste de nombres
Les nombres : {#each nombres as n}{n} {/each} !!
`
const data = {
nombres : [2,3,5,8]
}
const odtTemplate = await getOdtTemplate(templatePath)
const templateTextContent = await getOdtTextContent(odtTemplate)
t.deepEqual(templateTextContent, templateContent, 'reconnaissance du template')
const odtResult = await fillOdtTemplate(odtTemplate, data)
const odtResultTextContent = await getOdtTextContent(odtResult)
t.deepEqual(odtResultTextContent, `Liste de nombres
Les nombres : 2 3 5 8  !!
`)
});

Binary file not shown.