easy-template-x
Advanced tools
Comparing version 3.2.1 to 4.0.0
@@ -0,0 +0,0 @@ import { XmlTextNode } from "../xml"; |
@@ -0,0 +0,0 @@ import { DocxParser } from '../office'; |
@@ -0,0 +0,0 @@ export * from './delimiterMark'; |
import { TemplateContent, TemplateData } from '../templateData'; | ||
import { Tag } from './tag'; | ||
export declare type PathPart = Tag | number; | ||
export type PathPart = Tag | number; | ||
export interface ScopeDataArgs { | ||
@@ -9,3 +9,3 @@ path: PathPart[]; | ||
} | ||
export declare type ScopeDataResolver = (args: ScopeDataArgs) => TemplateContent | TemplateData[]; | ||
export type ScopeDataResolver = (args: ScopeDataArgs) => TemplateContent | TemplateData[]; | ||
export declare class ScopeData { | ||
@@ -12,0 +12,0 @@ static defaultResolver(args: ScopeDataArgs): TemplateContent | TemplateData[]; |
@@ -0,1 +1,2 @@ | ||
import { IMap } from '../types'; | ||
import { XmlTextNode } from '../xml'; | ||
@@ -9,2 +10,3 @@ export declare enum TagDisposition { | ||
name: string; | ||
options?: IMap<any>; | ||
rawText: string; | ||
@@ -11,0 +13,0 @@ disposition: TagDisposition; |
@@ -0,0 +0,0 @@ import { Delimiters } from '../delimiters'; |
@@ -0,0 +0,0 @@ import { TemplatePlugin } from '../plugins'; |
@@ -0,0 +0,0 @@ import { Docx, XmlPart } from '../office'; |
@@ -6,4 +6,6 @@ export declare class Delimiters { | ||
containerTagClose: string; | ||
tagOptionsStart: string; | ||
tagOptionsEnd: string; | ||
constructor(initial?: Partial<Delimiters>); | ||
private encodeAndValidate; | ||
} |
@@ -6,2 +6,3 @@ export * from './malformedFileError'; | ||
export * from './missingStartDelimiterError'; | ||
export * from './tagOptionsParseError'; | ||
export * from './unclosedTagError'; | ||
@@ -8,0 +9,0 @@ export * from './unidentifiedFileTypeError'; |
@@ -0,0 +0,0 @@ export declare class MalformedFileError extends Error { |
@@ -0,0 +0,0 @@ export declare class MaxXmlDepthError extends Error { |
@@ -0,0 +0,0 @@ export declare class MissingArgumentError extends Error { |
@@ -0,0 +0,0 @@ export declare class MissingCloseDelimiterError extends Error { |
@@ -0,0 +0,0 @@ export declare class MissingStartDelimiterError extends Error { |
@@ -0,0 +0,0 @@ export declare class UnclosedTagError extends Error { |
export declare class UnidentifiedFileTypeError extends Error { | ||
constructor(); | ||
} |
@@ -0,0 +0,0 @@ export declare class UnknownContentTypeError extends Error { |
@@ -0,0 +0,0 @@ export declare class UnopenedTagError extends Error { |
@@ -0,0 +0,0 @@ export declare class UnsupportedFileTypeError extends Error { |
@@ -0,0 +0,0 @@ import { TemplateExtension } from "./templateExtension"; |
export * from './extensionOptions'; | ||
export * from './templateExtension'; |
@@ -0,0 +0,0 @@ import { ScopeData, TagParser, TemplateCompiler, TemplateContext } from '../compilation'; |
@@ -0,0 +0,0 @@ export * from './compilation'; |
@@ -0,0 +0,0 @@ export declare enum MimeType { |
@@ -0,0 +0,0 @@ export declare enum ContentPartType { |
@@ -0,0 +0,0 @@ import { MimeType } from '../mimeType'; |
@@ -0,0 +0,0 @@ import { Constructor } from '../types'; |
@@ -0,0 +0,0 @@ import { XmlGeneralNode, XmlNode, XmlParser, XmlTextNode } from '../xml'; |
@@ -0,0 +0,0 @@ export * from './contentPartType'; |
@@ -0,0 +0,0 @@ import { MimeType } from '../mimeType'; |
import { XmlGeneralNode } from '../xml'; | ||
export declare type RelTargetMode = 'Internal' | 'External'; | ||
export type RelTargetMode = 'Internal' | 'External'; | ||
export declare class Relationship { | ||
@@ -4,0 +4,0 @@ static fromXml(xml: XmlGeneralNode): Relationship; |
@@ -0,0 +0,0 @@ import { XmlParser } from '../xml'; |
@@ -0,0 +0,0 @@ import { XmlNode, XmlParser } from '../xml'; |
import { TemplatePlugin } from './templatePlugin'; | ||
export declare function createDefaultPlugins(): TemplatePlugin[]; |
import { MimeType } from '../../mimeType'; | ||
import { Binary } from '../../utils'; | ||
import { PluginContent } from '../pluginContent'; | ||
export declare type ImageFormat = MimeType.Jpeg | MimeType.Png | MimeType.Gif | MimeType.Bmp | MimeType.Svg; | ||
export type ImageFormat = MimeType.Jpeg | MimeType.Png | MimeType.Gif | MimeType.Bmp | MimeType.Svg; | ||
export interface ImageContent extends PluginContent { | ||
@@ -6,0 +6,0 @@ _type: 'image'; |
@@ -0,0 +0,0 @@ import { ScopeData, Tag, TemplateContext } from '../../compilation'; |
export * from './imageContent'; | ||
export * from './imagePlugin'; |
@@ -0,0 +0,0 @@ export * from './image'; |
export * from './linkContent'; | ||
export * from './linkPlugin'; |
@@ -0,0 +0,0 @@ import { PluginContent } from '../pluginContent'; |
@@ -0,0 +0,0 @@ import { ScopeData, Tag, TemplateContext } from '../../compilation'; |
export * from './loopPlugin'; |
@@ -0,0 +0,0 @@ import { ScopeData, Tag, TemplateContext } from '../../compilation'; |
@@ -0,0 +0,0 @@ import { Tag } from '../../../compilation'; |
@@ -0,0 +0,0 @@ export * from './iLoopStrategy'; |
@@ -0,0 +0,0 @@ import { Tag } from '../../../compilation'; |
@@ -0,0 +0,0 @@ import { Tag } from '../../../compilation'; |
@@ -0,0 +0,0 @@ import { Tag } from '../../../compilation'; |
@@ -0,0 +0,0 @@ export interface PluginContent { |
export * from './rawXmlContent'; | ||
export * from './rawXmlPlugin'; |
@@ -0,0 +0,0 @@ import { PluginContent } from '../pluginContent'; |
@@ -0,0 +0,0 @@ import { ScopeData, Tag } from '../../compilation'; |
@@ -0,0 +0,0 @@ import { ScopeData, Tag, TemplateCompiler, TemplateContext } from '../compilation'; |
export * from './textPlugin'; |
@@ -0,0 +0,0 @@ import { ScopeData, Tag } from '../../compilation'; |
import { PluginContent } from './plugins'; | ||
export declare type PrimitiveTemplateContent = string | number | boolean; | ||
export declare type TemplateContent = PrimitiveTemplateContent | PluginContent; | ||
export type PrimitiveTemplateContent = string | number | boolean; | ||
export type TemplateContent = PrimitiveTemplateContent | PluginContent; | ||
export interface TemplateData { | ||
[tagName: string]: TemplateContent | TemplateData | TemplateData[]; | ||
} |
@@ -0,0 +0,0 @@ import { Tag } from './compilation'; |
@@ -0,0 +0,0 @@ import { ScopeDataResolver } from './compilation'; |
@@ -1,6 +0,4 @@ | ||
export interface IMap<T> { | ||
[key: string]: T; | ||
} | ||
export type IMap<T> = Record<string, T>; | ||
export interface Constructor<T> { | ||
new (...args: any[]): T; | ||
} |
import { IMap } from '../types'; | ||
export declare type ItemMapper<TIn, TOut = string> = (item: TIn, index: number) => TOut; | ||
export type ItemMapper<TIn, TOut = string> = (item: TIn, index: number) => TOut; | ||
export declare function pushMany<T>(destArray: T[], items: T[]): void; | ||
@@ -4,0 +4,0 @@ export declare function first<T>(array: T[]): T; |
export declare class Base64 { | ||
static encode(str: string): string; | ||
} |
@@ -1,4 +0,3 @@ | ||
/// <reference types="node" /> | ||
import { Constructor } from '../types'; | ||
export declare type Binary = Blob | Buffer | ArrayBuffer; | ||
export type Binary = Blob | Buffer | ArrayBuffer; | ||
export declare const Binary: { | ||
@@ -5,0 +4,0 @@ isBlob(binary: unknown): binary is Blob; |
@@ -0,0 +0,0 @@ export * from './array'; |
export declare function isNumber(value: unknown): value is number; |
@@ -0,0 +0,0 @@ export declare class Path { |
export declare class Regex { | ||
static escape(str: string): string; | ||
} |
export declare function sha1(msg: string): string; |
export declare function stringValue(val: unknown): string; | ||
export declare function normalizeDoubleQuotes(text: string): string; |
import { Constructor } from '../types'; | ||
export declare function inheritsFrom(derived: Constructor<any>, base: Constructor<any>): boolean; | ||
export declare function isPromiseLike<T>(candidate: unknown): candidate is PromiseLike<T>; |
export * from './xmlDepthTracker'; | ||
export * from './xmlNode'; | ||
export * from './xmlParser'; |
@@ -0,0 +0,0 @@ export declare class XmlDepthTracker { |
@@ -7,3 +7,3 @@ import { IMap } from '../types'; | ||
} | ||
export declare type XmlNode = XmlTextNode | XmlGeneralNode | XmlCommentNode; | ||
export type XmlNode = XmlTextNode | XmlGeneralNode | XmlCommentNode; | ||
export interface XmlNodeBase { | ||
@@ -10,0 +10,0 @@ nodeType: XmlNodeType; |
@@ -0,0 +0,0 @@ import { XmlNode } from './xmlNode'; |
export * from './zip'; | ||
export * from './zipObject'; |
@@ -0,0 +0,0 @@ import * as JSZip from 'jszip'; |
@@ -0,0 +0,0 @@ import { Constructor } from '../types'; |
@@ -0,0 +0,0 @@ import * as JSZip from 'jszip'; |
{ | ||
"name": "easy-template-x", | ||
"version": "3.2.1", | ||
"version": "4.0.0", | ||
"description": "Generate docx documents from templates, in Node or in the browser.", | ||
@@ -23,2 +23,3 @@ "keywords": [ | ||
}, | ||
"type": "module", | ||
"main": "dist/cjs/easy-template-x.js", | ||
@@ -42,4 +43,6 @@ "module": "dist/es/easy-template-x.js", | ||
}, | ||
"packageManager": "yarn@4.3.1", | ||
"dependencies": { | ||
"@xmldom/xmldom": "0.8.7", | ||
"@xmldom/xmldom": "0.8.10", | ||
"json5": "2.2.3", | ||
"jszip": "3.10.1", | ||
@@ -49,3 +52,3 @@ "lodash.get": "4.4.2" | ||
"devDependencies": { | ||
"@babel/core": "7.18.6", | ||
"@babel/core": "7.24.7", | ||
"@babel/plugin-proposal-class-properties": "7.18.6", | ||
@@ -56,26 +59,28 @@ "@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6", | ||
"@babel/plugin-proposal-optional-chaining": "7.18.6", | ||
"@babel/plugin-transform-modules-commonjs": "7.18.6", | ||
"@babel/preset-typescript": "7.18.6", | ||
"@rollup/plugin-replace": "4.0.0", | ||
"@types/jest": "28.1.4", | ||
"@babel/plugin-transform-modules-commonjs": "7.24.7", | ||
"@babel/preset-typescript": "7.24.7", | ||
"@eslint/js": "9.6.0", | ||
"@rollup/plugin-replace": "5.0.7", | ||
"@types/eslint__js": "8.42.3", | ||
"@types/jest": "29.5.12", | ||
"@types/jszip": "3.4.1", | ||
"@types/node": "18.0.1", | ||
"@types/ts-nameof": "4.2.1", | ||
"@typescript-eslint/eslint-plugin": "5.30.4", | ||
"@typescript-eslint/parser": "5.30.4", | ||
"babel-jest": "28.1.2", | ||
"babel-loader": "8.2.5", | ||
"@types/node": "20.14.9", | ||
"@types/ts-nameof": "4.2.5", | ||
"babel-jest": "29.7.0", | ||
"babel-loader": "9.1.3", | ||
"babel-plugin-ts-nameof": "4.2.1", | ||
"eslint": "8.19.0", | ||
"jest": "28.1.2", | ||
"eslint": "9.6.0", | ||
"globals": "15.8.0", | ||
"jest": "29.7.0", | ||
"jest-html-reporters": "3.1.7", | ||
"jest-junit": "14.0.0", | ||
"jest-junit": "16.0.0", | ||
"lorem-ipsum": "2.0.8", | ||
"rimraf": "3.0.2", | ||
"rollup": "2.75.7", | ||
"rimraf": "5.0.7", | ||
"rollup": "4.18.0", | ||
"rollup-plugin-auto-external": "2.0.0", | ||
"rollup-plugin-babel": "4.4.0", | ||
"rollup-plugin-node-resolve": "5.2.0", | ||
"typescript": "4.7.4" | ||
"typescript": "5.5.3", | ||
"typescript-eslint": "7.15.0" | ||
} | ||
} |
@@ -17,2 +17,3 @@ # easy-template-x | ||
- [Nested Conditions](#nested-conditions) | ||
- [Controlling loop behavior](#controlling-loop-behavior) | ||
- [Image plugin](#image-plugin) | ||
@@ -257,2 +258,35 @@ - [Link plugin](#link-plugin) | ||
#### Controlling loop behavior | ||
To control the loop (or condition) behavior you can use the `loopOver` option. | ||
Given this data: | ||
```javascript | ||
{ | ||
students: [ | ||
{ name: "Alice" }, | ||
{ name: "Bob" } | ||
] | ||
} | ||
``` | ||
You can use either this template: | ||
![input template](./docs/assets/loop-over-row-in.png?raw=true) | ||
Or this one: | ||
![input template](./docs/assets/loop-over-content-in.png?raw=true) | ||
The first will produce this document: | ||
![output document](./docs/assets/loop-over-row-out.png?raw=true) | ||
And the second will produce this one: | ||
![output document](./docs/assets/loop-over-content-out.png?raw=true) | ||
By default `easy-template-x` will loop over "content" if the opening and closing loop tags are in the same table cell and "row" otherwise. | ||
### Image plugin | ||
@@ -485,3 +519,5 @@ | ||
containerTagOpen: "#", | ||
containerTagClose: "/" | ||
containerTagClose: "/", | ||
tagOptionsStart: "[", | ||
tagOptionsEnd: "]" | ||
}, | ||
@@ -488,0 +524,0 @@ |
@@ -0,1 +1,2 @@ | ||
import { IMap } from '../types'; | ||
import { XmlTextNode } from '../xml'; | ||
@@ -9,4 +10,5 @@ | ||
export interface Tag { | ||
export interface Tag { | ||
name: string; | ||
options?: IMap<any>; | ||
/** | ||
@@ -18,2 +20,2 @@ * The full tag text, for instance: "{#my-tag}". | ||
xmlTextNode: XmlTextNode; | ||
} | ||
} |
@@ -0,5 +1,6 @@ | ||
import * as JSON5 from 'json5'; | ||
import { Delimiters } from '../delimiters'; | ||
import { MissingArgumentError, MissingCloseDelimiterError, MissingStartDelimiterError } from '../errors'; | ||
import { MissingArgumentError, MissingCloseDelimiterError, MissingStartDelimiterError, TagOptionsParseError } from '../errors'; | ||
import { DocxParser } from '../office'; | ||
import { Regex } from '../utils'; | ||
import { normalizeDoubleQuotes, Regex } from '../utils'; | ||
import { DelimiterMark } from './delimiterMark'; | ||
@@ -21,3 +22,4 @@ import { Tag, TagDisposition } from './tag'; | ||
this.tagRegex = new RegExp(`^${Regex.escape(delimiters.tagStart)}(.*?)${Regex.escape(delimiters.tagEnd)}`, 'm'); | ||
const tagOptionsRegex = `${Regex.escape(delimiters.tagOptionsStart)}(?<tagOptions>.*?)${Regex.escape(delimiters.tagOptionsEnd)}`; | ||
this.tagRegex = new RegExp(`^${Regex.escape(delimiters.tagStart)}(?<tagName>.*?)(${tagOptionsRegex})?${Regex.escape(delimiters.tagEnd)}`, 'm'); | ||
} | ||
@@ -140,4 +142,6 @@ | ||
const tagParts = this.tagRegex.exec(tag.rawText); | ||
const tagContent = (tagParts[1] || '').trim(); | ||
if (!tagContent || !tagContent.length) { | ||
const tagName = (tagParts.groups?.["tagName"] || '').trim(); | ||
// Ignoring empty tags. | ||
if (!tagName?.length) { | ||
tag.disposition = TagDisposition.SelfClosed; | ||
@@ -147,15 +151,30 @@ return; | ||
if (tagContent.startsWith(this.delimiters.containerTagOpen)) { | ||
// Tag options. | ||
const tagOptionsText = (tagParts.groups?.["tagOptions"] || '').trim(); | ||
if (tagOptionsText) { | ||
try { | ||
tag.options = JSON5.parse("{" + normalizeDoubleQuotes(tagOptionsText) + "}"); | ||
} catch (e) { | ||
throw new TagOptionsParseError(tag.rawText, e); | ||
} | ||
} | ||
// Container open tag. | ||
if (tagName.startsWith(this.delimiters.containerTagOpen)) { | ||
tag.disposition = TagDisposition.Open; | ||
tag.name = tagContent.slice(this.delimiters.containerTagOpen.length).trim(); | ||
tag.name = tagName.slice(this.delimiters.containerTagOpen.length).trim(); | ||
return; | ||
} | ||
} else if (tagContent.startsWith(this.delimiters.containerTagClose)) { | ||
// Container close tag. | ||
if (tagName.startsWith(this.delimiters.containerTagClose)) { | ||
tag.disposition = TagDisposition.Close; | ||
tag.name = tagContent.slice(this.delimiters.containerTagClose.length).trim(); | ||
tag.name = tagName.slice(this.delimiters.containerTagClose.length).trim(); | ||
return; | ||
} | ||
} else { | ||
tag.disposition = TagDisposition.SelfClosed; | ||
tag.name = tagContent; | ||
} | ||
// Self-closed tag. | ||
tag.disposition = TagDisposition.SelfClosed; | ||
tag.name = tagName; | ||
} | ||
} |
@@ -8,2 +8,4 @@ | ||
public containerTagClose = "/"; | ||
public tagOptionsStart = "["; | ||
public tagOptionsEnd = "]"; | ||
@@ -31,2 +33,2 @@ constructor(initial?: Partial<Delimiters>) { | ||
} | ||
} | ||
} |
@@ -6,2 +6,3 @@ export * from './malformedFileError'; | ||
export * from './missingStartDelimiterError'; | ||
export * from './tagOptionsParseError'; | ||
export * from './unclosedTagError'; | ||
@@ -8,0 +9,0 @@ export * from './unidentifiedFileTypeError'; |
@@ -9,6 +9,3 @@ export class MalformedFileError extends Error { | ||
this.expectedFileType = expectedFileType; | ||
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
Object.setPrototypeOf(this, MalformedFileError.prototype); | ||
} | ||
} | ||
} |
@@ -9,6 +9,3 @@ export class MaxXmlDepthError extends Error { | ||
this.maxDepth = maxDepth; | ||
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
Object.setPrototypeOf(this, MaxXmlDepthError.prototype); | ||
} | ||
} | ||
} |
@@ -9,6 +9,3 @@ export class MissingArgumentError extends Error { | ||
this.argName = argName; | ||
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
Object.setPrototypeOf(this, MissingArgumentError.prototype); | ||
} | ||
} | ||
} |
@@ -9,6 +9,3 @@ export class MissingCloseDelimiterError extends Error { | ||
this.openDelimiterText = openDelimiterText; | ||
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
Object.setPrototypeOf(this, MissingCloseDelimiterError.prototype); | ||
} | ||
} | ||
} |
@@ -9,6 +9,3 @@ export class MissingStartDelimiterError extends Error { | ||
this.closeDelimiterText = closeDelimiterText; | ||
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
Object.setPrototypeOf(this, MissingStartDelimiterError.prototype); | ||
} | ||
} | ||
} |
@@ -9,6 +9,3 @@ export class UnclosedTagError extends Error { | ||
this.tagName = tagName; | ||
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
Object.setPrototypeOf(this, UnclosedTagError.prototype); | ||
} | ||
} | ||
} |
export class UnidentifiedFileTypeError extends Error { | ||
constructor() { | ||
super(`The filetype for this file could not be identified, is this file corrupted?`); | ||
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
Object.setPrototypeOf(this, UnidentifiedFileTypeError.prototype); | ||
} | ||
} | ||
} |
@@ -13,6 +13,3 @@ export class UnknownContentTypeError extends Error { | ||
this.path = path; | ||
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
Object.setPrototypeOf(this, UnknownContentTypeError.prototype); | ||
} | ||
} | ||
} |
@@ -9,6 +9,3 @@ export class UnopenedTagError extends Error { | ||
this.tagName = tagName; | ||
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
Object.setPrototypeOf(this, UnopenedTagError.prototype); | ||
} | ||
} | ||
} |
@@ -9,6 +9,3 @@ export class UnsupportedFileTypeError extends Error { | ||
this.fileType = fileType; | ||
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
Object.setPrototypeOf(this, UnsupportedFileTypeError.prototype); | ||
} | ||
} | ||
} |
@@ -32,3 +32,3 @@ import { PathPart, ScopeData, Tag, TemplateContext } from '../../compilation'; | ||
if (isCondition) { | ||
if (!!value) { | ||
if (value) { | ||
value = [{}]; | ||
@@ -35,0 +35,0 @@ } else { |
import { Tag } from '../../../compilation'; | ||
import { XmlNode } from '../../../xml'; | ||
import { PluginUtilities } from '../../templatePlugin'; | ||
import { LoopOver, LoopTagOptions } from '../loopTagOptions'; | ||
import { ILoopStrategy, SplitBeforeResult } from './iLoopStrategy'; | ||
@@ -15,6 +16,24 @@ | ||
public isApplicable(openTag: Tag, closeTag: Tag): boolean { | ||
const containingParagraph = this.utilities.docxParser.containingParagraphNode(openTag.xmlTextNode); | ||
if (!containingParagraph.parentNode) | ||
const openParagraph = this.utilities.docxParser.containingParagraphNode(openTag.xmlTextNode); | ||
if (!openParagraph.parentNode) | ||
return false; | ||
return this.utilities.docxParser.isTableCellNode(containingParagraph.parentNode); | ||
if (!this.utilities.docxParser.isTableCellNode(openParagraph.parentNode)) | ||
return false; | ||
const closeParagraph = this.utilities.docxParser.containingParagraphNode(closeTag.xmlTextNode); | ||
if (!closeParagraph.parentNode) | ||
return false; | ||
if (!this.utilities.docxParser.isTableCellNode(closeParagraph.parentNode)) | ||
return false; | ||
const options = openTag.options as LoopTagOptions; | ||
const forceRowLoop = options?.loopOver === LoopOver.Row; | ||
// If both tags are in the same cell, assume it's a paragraph loop (iterate content, not rows). | ||
if (!forceRowLoop && openParagraph.parentNode === closeParagraph.parentNode) | ||
return false; | ||
return true; | ||
} | ||
@@ -21,0 +40,0 @@ |
@@ -11,4 +11,2 @@ import { ScopeData, Tag, TemplateCompiler, TemplateContext } from '../compilation'; | ||
/* eslint-disable @typescript-eslint/member-ordering */ | ||
export abstract class TemplatePlugin { | ||
@@ -15,0 +13,0 @@ |
export interface IMap<T> { | ||
[key: string]: T; | ||
} | ||
export type IMap<T> = Record<string, T>; | ||
@@ -6,0 +4,0 @@ export interface Constructor<T> { |
@@ -1,2 +0,26 @@ | ||
export function stringValue(val: unknown) : string { | ||
// Copied from: https://gist.github.com/thanpolas/244d9a13151caf5a12e42208b6111aa6 | ||
// And see: https://unicode-table.com/en/sets/quotation-marks/ | ||
const nonStandardDoubleQuotes = [ | ||
'“', // U+201c | ||
'”', // U+201d | ||
'«', // U+00AB | ||
'»', // U+00BB | ||
'„', // U+201E | ||
'“', // U+201C | ||
'‟', // U+201F | ||
'”', // U+201D | ||
'❝', // U+275D | ||
'❞', // U+275E | ||
'〝', // U+301D | ||
'〞', // U+301E | ||
'〟', // U+301F | ||
'"', // U+FF02 | ||
]; | ||
const standardDoubleQuotes = '"'; // U+0022 | ||
const nonStandardDoubleQuotesRegex = new RegExp(nonStandardDoubleQuotes.join('|'), 'g'); | ||
export function stringValue(val: unknown): string { | ||
if (val === null || val === undefined) { | ||
@@ -7,1 +31,5 @@ return ''; | ||
} | ||
export function normalizeDoubleQuotes(text: string): string { | ||
return text.replace(nonStandardDoubleQuotesRegex, standardDoubleQuotes); | ||
} |
@@ -149,9 +149,11 @@ import { MissingArgumentError } from '../errors'; | ||
switch (domNode.nodeType) { | ||
case domNode.TEXT_NODE: | ||
case domNode.TEXT_NODE: { | ||
xmlNode = this.createTextNode(domNode.textContent); | ||
break; | ||
case domNode.COMMENT_NODE: | ||
} | ||
case domNode.COMMENT_NODE: { | ||
xmlNode = this.createCommentNode(domNode.textContent?.trim()); | ||
break; | ||
case domNode.ELEMENT_NODE: | ||
} | ||
case domNode.ELEMENT_NODE: { | ||
const generalNode = xmlNode = this.createGeneralNode(domNode.nodeName); | ||
@@ -167,5 +169,7 @@ const attributes = (domNode as Element).attributes; | ||
break; | ||
default: | ||
} | ||
default: { | ||
xmlNode = this.createGeneralNode(domNode.nodeName); | ||
break; | ||
} | ||
} | ||
@@ -172,0 +176,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
398507
167
10112
608
Yes
4
31
+ Addedjson5@2.2.3
+ Added@xmldom/xmldom@0.8.10(transitive)
+ Addedjson5@2.2.3(transitive)
- Removed@xmldom/xmldom@0.8.7(transitive)
Updated@xmldom/xmldom@0.8.10