Giter Club home page Giter Club logo

easy-template-x's People

Contributors

alonrbar avatar beansampa avatar dependabot[bot] avatar ggalas avatar kwokhou avatar sebastianrogers avatar thegnuu avatar timnieder avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

easy-template-x's Issues

Not being able to display an array inside if condition

Hello everyone,

I have been trying to display an array inside if condition.
Here is the template I use inside myc docx file:

{#participants}
{#display}
{name}
	{#list}
		Name : {name}
		Surname : {surname}	
	{/list}
{/}
{/ participants }

And here is the data I pass to the template:

       const data = {
            "participants": [
                {
                    "display": true,
                    "name" : "bob",
                    "list": [
                        { "no": 1, "name": "Bryson", "surname": "Pike" },
                    ]
                },
                {
                    "display": true,
                    "name" : "alice",
                    "list": [
                        { "no": 3, "name": "Charis", "surname": "Hilton" },
                        { "no": 4, "name": "John", "surname": "Plant" },
                    ]
                },
                {
                    "display": false,
                    "name" : "bruno",
                    "list": [
                        { "no": 6, "name": "Beatriz", "surname": "Schmitt" },
                        { "no": 7, "name": "Fionn", "surname": "Lyons" },
                        { "no": 8, "name": "Pedro", "surname": "Compton" }
                    ]
                }
            ]
        }


        const handler = new TemplateHandler();
        const doc = await handler.process(templateFile, data);

And here is a screenshot of the output.docx file generated :
image

As you can see the name displayed is the name of participants and not the in in the list, also no surname is displayed..

Am I doing something wrong in the template or is this not supported with easy-template-x ?

PS: if I remove the condition {#display} {/} it works fine and displays the right values, so it seems that the problem is doing a loop inside a condition.

Thank you!

Multiple enhancements

@alonrbar I worked quite a while at your project today and changed a few things, here is what I've done:

  • Webpack: switched from babel to ts-loader to automatically generate types
  • Wepack: switched from UglifyJsPlugin to TerserPlugin because of issues with the new webpack version
  • Jest: because of the webpack change i switched to ts-jest to omit the babel configs
  • Imports: optimized all imports to relative paths because I ran into some weird issues while generating types
  • Imports: switched to one index.ts to provide one entry point for the public api
  • Style: added a prettier config and editorconfig
  • Plugins: changed a few types to more generic ones like the PluginContent to prevent type errors while creating new plugins
  • Deps: updated all dependencies

You can find my changes here https://github.com/bbit-cloud/easy-template-x.

I don't know if you are happy with those changes because I touched nearly every file, if you think this all makes sense I am happy to provide a pull request :)

Keep {tag} if value null

It's possible to keep {tag} if the value is null, empty string, etc? For single value I just replace do replacing like this:
orderDate: currentClaim.orderDate ? moment(currentClaim.orderDate).format("DD.MM.YYYY") : "{orderDate}",

But how do it for arrays?

{#reviews}{position} {submitted} {acceptanceText} {fullName}{/reviews}

Question: Rendering XML with pStyle

Hi all,

This is a question since I have some issues rendering content in a custom plugin, not an issue with the library itself I guess, but maybe some with more word-xml experience has an idea....

I am currently working on a plugin to render prosemirror editor content to a word template, this is required in my project since some rich text parts have to be rendered dynamically.

It was not an issue to render simple styles like bold, italic or some color for text nodes. But as soon as I try to render some pStyles they get not properly applied.

For example if i try to render headings the following output is generated:

Screenshot 2021-10-25 at 12 05 10

But it should look like this:

Screenshot 2021-10-25 at 12 05 46

As you can see, the Heading1 style is applied properly, Heading2 and Heading3 are not working.

A similar issue happens with Bullet and ordered lists:

generated:
Screenshot 2021-10-25 at 13 13 28

manually:
Screenshot 2021-10-25 at 12 08 20

As you can see here, the XML are basically identically... Adding all the IDs so they match up with de document does not change a thing.... As you can see in the generated styles the numId with value 1 is ignored here

Manually added styles:

  <w:p w14:paraId="531E0080" w14:textId="5F7940E5" w:rsidR="00F06626" w:rsidRPr="00F06626" w:rsidRDefault="00F06626" w:rsidP="00F06626">
      <w:pPr>
        <w:pStyle w:val="ListParagraph"/>
        <w:numPr>
          <w:ilvl w:val="0"/>
          <w:numId w:val="1"/>
        </w:numPr>
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
      </w:pPr>
      <w:r w:rsidRPr="00F06626">
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
        <w:t>Bullet list 1</w:t>
      </w:r>
    </w:p>
    <w:p w14:paraId="49BB712D" w14:textId="1F7AE020" w:rsidR="00F06626" w:rsidRPr="00F06626" w:rsidRDefault="00F06626" w:rsidP="00F06626">
      <w:pPr>
        <w:pStyle w:val="ListParagraph"/>
        <w:numPr>
          <w:ilvl w:val="0"/>
          <w:numId w:val="1"/>
        </w:numPr>
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
      </w:pPr>
      <w:r w:rsidRPr="00F06626">
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
        <w:t>Bullet list 2</w:t>
      </w:r>
    </w:p>

generated styles:

    <w:p>
      <w:pPr>
        <w:pStyle w:val="ListParagraph"/>
        <w:numPr>
          <w:ilvl w:val="0"/>
          <w:numId w:val="1"/>
        </w:numPr>
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
      </w:pPr>
      <w:r>
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
        <w:t xml:space="preserve">Bullet list 1</w:t>
      </w:r>
    </w:p>
    <w:p>
      <w:pPr>
        <w:pStyle w:val="ListParagraph"/>
        <w:numPr>
          <w:ilvl w:val="0"/>
          <w:numId w:val="1"/>
        </w:numPr>
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
      </w:pPr>
      <w:r>
        <w:rPr>
          <w:lang w:val="en-US"/>
        </w:rPr>
        <w:t xml:space="preserve">Bullet list 2</w:t>
      </w:r>
    </w:p>

Has anyone an idea what I can to to fix this?

Thanks a lot!

Detect tags without replacement option

Is it possible to detect tags that don't have any corresponding data to be replaced into.

For example:

Data:

{
  "Beers": [
    { "Brand": "Carlsberg" },
    { "Brand": "Leaf Blonde" },
    { "Brand": "Weihenstephan" }
  ]
}

Tags in my template:
{#Beers}{Brand}_{Price}${/Beers}

Can I detect that {Price} doesn't have any data and get that tag?

Base64 image

Hi,
Can I add a base64 image instead of file?

Nested conditions in a table

image

In the above image you can see the issue. If the condition in the red square (cond8) is set to false, the entire cell is shown empty, even though cond7 is set to true. If both are set to true, everything shows up.

How to embed an image

I can see that you support binary, but how exactly does one go about embedding an image from the JSON data into the template?

Many thanks!

Corrupted file when writeFileSync and encounter weird behavior

I have the following code to test and parse the file test.docx. But seem weird that the file is corrupted when we have the content inside beginning with the word certificate, and if I remove the leading certificate word inside the docx file. The convert is success. Can anybody explain?

const { TemplateHandler } = require("easy-template-x");
const fs = require("fs");
const unoconv = require('awesome-unoconv');


const parseDoc = async () => {
    const handler = new TemplateHandler();
    try {
        const templateFile = fs.readFileSync('test.docx');

        const data = {
            name: 'test',
            unit_number: '1111',
        };
        const updatedDoc = await handler.process(templateFile, data);
        fs.writeFileSync('test.docx', updatedDoc); // success convert but when write the file it become corrupted
        await unoconv.convert('test.docx', 'test.pdf');
    } catch (error) {
        // thow error here
        console.log(error)
    }

}

parseDoc();

Error:

The document 'file:///var/www/sparebox-admin/test.docx' could not be opened.

    at ChildProcess.<anonymous> (/var/www/sparebox-admin/node_modules/awesome-unoconv/dist/converter.js:147:23)
    at ChildProcess.emit (events.js:198:13)
    at maybeClose (internal/child_process.js:982:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:259:5)

test.docx: this file would cause an error with the word "certificate" leading

test.docx: this file is successful without the word "certificate" leading

Version:
"easy-template-x": "^1.0.1" and "easy-template-x": "^2.1.0"
"awesome-unoconv": "^1.0.1"

How to get parent field within a loop when names conflict

Hi, very interested in this library, but a few questions.

Suppose this data structure:

const data = {
    posts: [
        { author: 'Alon Bar', text: 'Very important\ntext here!', fans: [{ text: 'A' }, {text: 'B'}] },
        { author: 'Alon Bar', text: 'Forgot to mention that...', fans: [{ text: 'A' }, {text: 'B'}] }
    ]
};

How do I fix this template:

{#posts}
Author: {author}
{text}
    {#fans}
    {text} < I want the post text here
    {text} < I want the fan text here
    {/fans}
{/posts}

Let's ignore how rubbish an example this is... but the principle remains: how would I target a the parent text and the new child text from within the second loop?

Many thanks

Edge support

Hi,

Did you test this against Edge? Can't seem to get it to work, nor does the live demo work on Edge. Firefox seems to run OK, not sure about Chrome.

Getting

0: Invalid calling object easy-template-x.js (1859,1)

Presumably in the following code block

  async getDocument() {
    if (!this._document) {
      const xml = await this.zip.getFile(this.documentPath).getContentText();
      this._document = this.xmlParser.parse(xml);
    }

    return this._document;
  }

File crash with hyperlink and hashtag

First of all congratulations for this library.

After testing your library I discovered a bug. When you put a hyperlink with a hashtag, the file crashes.

Corrupto.docx
This file doesn't work, because it has a hashtag in the hyperlink.

Funciona.docx
But this file works because it doesn´t have a hashtag in the hyperlink.

Could you check it? thanks 😊

Browser Version

Hi,
It looks like a very useful plugin.
I want to try this in a standard Javascript in browser, without typescript, import, export.
Your browser version is in Typescript.
Can you provide the standard JS to work in browser and code snippet?
Thanks,
Muthu

Headers are ignored

Is there any way to replace variables in the header of a word file, when using a custom template on the demo page it did not replace any of the header text.

Is it possible to embed one or more spreadsheets?

I'd like to insert spreadsheets, but not sure how it's possible?
I'm guessing maybe with rawXML, but I can't figure out how to start..

In Libreoffice Writer it can be done manually by choosing Insert > Object > Ole Object > Create new LibreOffice 7 Spreadsheet.
I suppose it's similar in Microsoft Word.

I've attached an example docx for reference.

image
embedded_spreadsheet_example.docx

Accessing object property

My data (received from backend API) is organized as hierarchical content. How can access an object property within a template file

Something like {project.client.title}

I found no way to make it work

Browser Example

Browser example for the README.md file:

Browser Example

import {TemplateHandler} from 'easy-template-x';
import save from 'save-file';
import JSZip from 'jszip';
import JSZipUtils from 'jszip-utils';

loadFile = (url,callback) => {
JSZipUtils.getBinaryContent(url,callback);
}

myEasyTemplate = () => {
this.loadFile("myTemplate.docx",function(error,content){
if (error) { throw error };

    const data = {
        posts: [
            { author: 'Easy', text: 'Very important\ntext here!' },
            { author: 'Easy', text: 'Forgot to mention that...' }
        ]
    };

    const handler = new TemplateHandler();
    handler.process(content, data).then(doc => 
    {
        save.sync(doc, "easy-output.docx");        
    });
})

}

Nested loop in a table

First of all.. Thank you so much for this library!

I´ve encounter a possible bug when we write something like {#table}{Property1}{#images}{image}{/images}{Property2}{/Table}. All the information is visible but each image is separated with a row with the same information from property1 and property2.

Already tried to separate the tags with new line but with no success..

Some prints below.. Any help is appreciated, thanks!

Screenshot 2021-05-20 at 19 54 02

Screenshot 2021-05-20 at 19 54 29

Images in nested arrays

Hi, it's me again. Now I'm having a new trouble wich is that I have a nested array with images inside and when I print the document it just writes [object Object].

My array looks like this:
items [ name: 'product 1', description: 'Description for product 1 here....', image: { _type: 'image', source: <source> format: 'image/png', width, height, }, name: 'product 2', description: 'Description for product 2 here....', image: { _type: 'image', source: <source> format: 'image/png', width, height, }, ]

and my docx document looks like this:
{#items} {name} {description} {image} {/items}

It prints the name and description correctly, but for the image prints [object Object]

Help!:(

Picture is empty in word file

I added an image to a list but only show blank box in word.

{ "Brand": "Carlsberg",
"Price": 1 ,
"image": {
_type: "image",
source: fs.readFileSync("./res/image-plugin-out.png"),
format: "image/png",
width: 371,
height: 387
}
}

Any help would be grateful.
François

Conditions

Are there any plans to support conditions?

We used docxtemplater before but we would like to switch to this project because of the ability to add custom plugins (we need this feature to properly render Deltas from the quill editor).

Of course I can try to implement conditions with a plugin, but I think this would be a nice general feature for this project :)

The package is not compatible with Vite in production build: `require is not defined`

I am migrating my project from webpack to vite. When building the project for production using Rollup under the hood I get the following error:

require is not defined

The reason is that Vite works only with ES modules and is not compatible with CommonJS. Diving deeper I stated that require is used in src/compilation/scopeData.ts:

const getProp = require("lodash.get");

As the result, ESM version of this package contains this require in the build. In order to fix the issue the dependency should be imported like this:

import getProp from 'lodash.get';

As a quick workaround I managed to apply the following patch to 3.0.0 using patch-package:

diff --git a/node_modules/easy-template-x/dist/es/easy-template-x.js b/node_modules/easy-template-x/dist/es/easy-template-x.js
index 641554d..f0d43f0 100644
--- a/node_modules/easy-template-x/dist/es/easy-template-x.js
+++ b/node_modules/easy-template-x/dist/es/easy-template-x.js
@@ -1163,7 +1163,7 @@ class DelimiterSearcher {
 
 }
 
-const getProp = require("lodash.get");
+import getProp from 'lodash.get';
 
 class ScopeData {
   static defaultResolver(args) {

Adding plugins from an angular project

Hi @alonrbar,

Me again ;) This has not a high priority for me personally, but it might become an issue for other users.

I am currently implementing new plugins. Adding the plugins directly in my fork works great, but if I try to do this from "outside" in my example from my angular application the following error occurs:

TypeError: Class constructor TemplatePlugin cannot be invoked without 'new'

I had no time to dig into this issue further, I have to prepare a release of the new version of our app and will stick to implement it in my fork.

I will update this issue as soon as I found something helpful.

Unable to use easy.template-x on the browser

I'm trying to compile easy-template-x for using it on the browser but all my attempts failed.
Is there a precompiled .js file or an explanation to compile and include it on the borwser?
Thanks so much in advance.

Error "Binary type 'Buffer' is not supported." when I call handler.process.

Hello. I have an error "Binary type 'Buffer' is not supported." when I call handler.process. But handler.getText and getXml work fine.

const templateFile = await fs.readFileSync( exportDir + fileName);

        const data = {
            Country: country,
        };

        const handler = new TemplateHandler({
            delimiters: {
                start: '{',
                end: '}'
            }
        });

        const doc = await handler.process(templateFile, data);

Random text in output file

I am trying a basic test run with this package. But when I try to run the code, the output is just long line of string.
source: test.docx
ouutput file (generated): output.docx

Code:

const fs = require("fs");
const path = require("path");

const { TemplateHandler } = require("easy-template-x");

const templateFile = fs.readFileSync(path.join(__dirname, "test.docx"));

// 2. process the template
const data = {
  name: "sha",
  bio: "bla"
};

const handler = new TemplateHandler();
const gendoc = async () => {
  const doc = await handler.process(templateFile, data);
  fs.writeFileSync("myTemplate - output.docx", doc);
};

// 3. save output
gendoc();

Node version: 16.15.1

How to add hyper link

I have a question as to how can one add a hyperlink?

Like it is done in this project docx-templates :- Links

An accessor cannot be declared in an ambient context.

I get "An accessor cannot be declared in an ambient context." in multiple files when running npm start.
Is the issue that I am running on a too old version of typescript or something else?
I am currently running Typescript 2.7.2 and Angular 6.1.

Converting to PDF

First of all thanks for this amazing library. Great work.
Is there a chance to add convert to pdf feature? Preferably without 3rd party libraries (LibreOffice etc.)

I found this library but it's too slow with buffer

Repeat multiple rows in a table

Hello,

I have a question.

In my template, each row of data is represented by one table.
But what I'm not able to achieve is to remove empty lines caused by the Loop start tag & the Loop end tag.

I prepared a simplified demo https://codesandbox.io/s/easy-template-x-demo-forked-m6061 where you can try it.
At the bottom is a preview of what is generated and what I what to achieve.

The only problem is empty lines between tables.

  • when I try to put the start and the end tag for loop into the table, then it adds one table row without data
  • put Start tag into a table and End tag after the table is not possible because then engine throws "Error: Argument 'lastNode' is missing."

Do you think that this problem can be somehow solved?

Thank you

Get data structure/tree from docx template

Greetings!

First of all, thank you very much for all the work you put in thus far. I really like the concept and I think it can be greatly expanded upon. For my current use case, I need to read the docx template, and then extract the tags, but in a hierarchical order.

Could you point me in the right direction in terms of how to achieve this? I tried digging into the libraries depths but was a little overwhelmed by the complexity since I have no experience working with XML.

As an example though, say we have the following tags in a template (which I know I can get from parseTags)

{color}
{#master}
{author}
{#nest_1_cond}
{copyright}
{/}
{#nest_2_cond}
{someVar}
{/}
(/)
(subject)

this should result in the following object

{
  color: "",
  master: {
    author: "",
    nest_1_cond: {
      copyright: "",
    },
    nest_1_cond: {
      someVar: "",
    },
  },
 subject:""
}

I know there are some problems with this right of the bat. For example,

  1. how do I distinguish between a table-loop, and a simple condition loop?
  2. Also, I noticed I can not place two conditionals in a row without wrapping them inside another condition, like the above nest_1_cond and nest_2_cond which are wrapped inside the master.

I am half sure that this functionality is already there, at least in reverse since you somehow need to find all the tags and all the loops for the loop functionality. But I am unsure on how to reverse construct an object from that, if that is even practicable. If you have any suggestions, ideas or further reading - I 'll gladly take it

array of attachments

for example:
i have array of images like

attachments: [{
          _type: 'image',
          source: readFileSync('hero.png').buffer,
          format: 'images/png',
          width: 200,
          height: 200,
}, {...}, {...}],

how should i write the template file?

Configure placeholder

My word document has a placeholder which is <<insert>> . Can we configure the placeholder as <<>> instead of {} ?

Unknown prefix with simple text replacement

I have a simple .docx file that only contains

{Last Name}, {First Name}: {Address}

When I call
await handler.parseTags(this.file.value)

I get an error:

core.js:6014 ERROR Error: Uncaught (in promise): Error: Tag '' does not match any of the known prefixes.
Error: Tag '' does not match any of the known prefixes.
    at TagParser.processTag (easy-template-x.js:2419)
    at TagParser.parse (easy-template-x.js:2348)
    at TemplateCompiler.parseTags (easy-template-x.js:2477)
    at TemplateHandler.parseTags (easy-template-x.js:4441)
    at resolvePromise (zone-evergreen.js:797)
    at zone-evergreen.js:707
    at rejected (tslib.es6.js:71)
    at ZoneDelegate.invoke (zone-evergreen.js:359)
    at Object.onInvoke (core.js:39698)
    at ZoneDelegate.invoke (zone-evergreen.js:358)
    at Zone.run (zone-evergreen.js:124)
    at zone-evergreen.js:855
    at ZoneDelegate.invokeTask (zone-evergreen.js:391)
    at Object.onInvokeTask (core.js:39679)

But if I remove {Address} then it parses the tags fine.

Embedded arrays or nested arrays

Hi! I'm having some trouble with some nested arrays with objects. In my document I do this:
{#array} {property1} {property2} {#nestedArray} {propertyOneOfNestedArray} {/nestedArray} {/array}

Obviously this is an example, but this is some kind of example that I'm trying to do.

Sorry for my english.

Unable to replace Image in Browser

Hey guys,
i was trying to replace an image in a react-app by following the documentation. Text replacing is working fine but image replacing is just not working.
You can have a look at my codesandbox. If you remove the image property in the data object its working but when i try to replace with image property, it´s giving me the following error message (Binary type 'Promise' is not supported). So im wondering if there is something wrong with my image format or if there´s another problem. I tried with blob and ArrayBuffer.
Hope you guys can help me here.
Thanks

PS: Since downloading contents at codesandbox is not working anymore i just logged the error.

Tags inside conditions (in a table)

Hello again :)

Another question, is it possible to add a simple text tag inside a condition? If yes, what´s the approach?

i want something like this
Screenshot 2021-05-21 at 13 04 10

and i´ve tried using the #lines example and the other tags outside..
Screenshot 2021-05-21 at 13 10 01
i get Node has no Parent Error

next i tried this
Screenshot 2021-05-21 at 13 12 36
and this
Screenshot 2021-05-21 at 13 31 27

same error.. any hint on how to achieve this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.