Merge pull request #9 from dolanmiu/master

Upd to latest version of docx js
This commit is contained in:
Andrey Savin
2022-12-07 21:58:14 +02:00
committed by GitHub
13 changed files with 1056 additions and 838 deletions

1
.npmrc Normal file
View File

@ -0,0 +1 @@
registry=https://registry.npmjs.org/

View File

@ -29,11 +29,12 @@ Here are examples of `docx` being used with basic `HTML/JS` in a browser environ
- https://codepen.io/dolanmiu/pen/RwNeObg
- https://jsfiddle.net/dolanmiu/onadx1gu/
Here is an example of `docx` working in `Angular`:
Here are examples of `docx` working in `Angular`:
- https://stackblitz.com/edit/angular-docx
- https://stackblitz.com/edit/angular-wmd6k3
Here is an example of `docx` working in `React`:
Here are examples of `docx` working in `React`:
- https://stackblitz.com/edit/react-docx
- https://stackblitz.com/edit/react-docx-images (adding images to Word Document)

View File

@ -14,6 +14,7 @@ const doc = new Document({
new TextRun({
text: "Foo Bar",
bold: true,
size: 40,
}),
new TextRun({
children: [new Tab(), "Github is the best"],

View File

@ -222,6 +222,15 @@ const doc = new Document({
new TextRun({
text: "Underline and Strike",
}),
new TextRun({
text: " Override Underline ",
underline: {
type: UnderlineType.NONE,
},
}),
new TextRun({
text: "Strike and Underline",
}),
],
}),
new Paragraph({

View File

@ -0,0 +1,27 @@
// Simple example to add text to a document
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { AlignmentType, Document, Packer, Paragraph, TextRun } from "../build";
const doc = new Document({
sections: [
{
properties: {},
children: [
new Paragraph({
alignment: AlignmentType.THAI_DISTRIBUTE,
children: [
new TextRun({
text: "บริษัท บิสกิด จำกัด (บริษัทฯ) ได้จดทะเบียนจัดตั้งขึ้นเป็นบริษัทจำกัดตามประมวลกฎหมายแพ่งและพาณิชย์ของประเทศไทย เมื่อวันที่ 30 พฤษภาคม 2561 ทะเบียนนิติบุคคลเลขที่ 0845561005665",
size: 36,
}),
],
}),
],
},
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,193 @@
// Example of how you would create a table and add data to it from a data source
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import {
Document,
HeadingLevel,
Packer,
Paragraph,
Table,
TableCell,
TableRow,
VerticalAlign,
TextDirection,
TextRun,
WidthType,
} from "../build";
interface StockPrice {
readonly date: Date;
readonly ticker: string;
readonly price: number;
}
const DATA: StockPrice[] = [
{
date: new Date("2007-08-28"),
ticker: "Apple",
price: 18.12,
},
{
date: new Date("2007-08-29"),
ticker: "Apple",
price: 19.15,
},
{
date: new Date("2007-08-30"),
ticker: "Apple",
price: 19.46,
},
{
date: new Date("2007-08-31"),
ticker: "Apple",
price: 19.78,
},
{
date: new Date("2007-09-04"),
ticker: "Apple",
price: 20.59,
},
{
date: new Date("2007-09-05"),
ticker: "Apple",
price: 19.54,
},
{
date: new Date("2007-09-06"),
ticker: "Apple",
price: 19.29,
},
{
date: new Date("2007-09-07"),
ticker: "Apple",
price: 18.82,
},
{
date: new Date("2007-09-10"),
ticker: "Apple",
price: 19.53,
},
{
date: new Date("2007-09-11"),
ticker: "Apple",
price: 19.36,
},
{
date: new Date("2007-09-12"),
ticker: "Apple",
price: 19.55,
},
{
date: new Date("2007-09-13"),
ticker: "Apple",
price: 19.6,
},
{
date: new Date("2007-09-14"),
ticker: "Apple",
price: 19.83,
},
{
date: new Date("2007-09-17"),
ticker: "Apple",
price: 19.77,
},
];
const generateRows = (prices: StockPrice[]): TableRow[] =>
prices.map(
({ date, ticker, price }) =>
new TableRow({
children: [
new TableCell({
children: [new Paragraph(date.toString())],
verticalAlign: VerticalAlign.CENTER,
textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM,
}),
new TableCell({
children: [new Paragraph(ticker)],
verticalAlign: VerticalAlign.CENTER,
textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM,
}),
new TableCell({
children: [new Paragraph(price.toString())],
verticalAlign: VerticalAlign.CENTER,
textDirection: TextDirection.TOP_TO_BOTTOM_RIGHT_TO_LEFT,
}),
],
}),
);
const doc = new Document({
sections: [
{
children: [
new Table({
width: {
size: 9070,
type: WidthType.DXA,
},
rows: [
new TableRow({
children: [
new TableCell({
children: [
new Paragraph({
heading: HeadingLevel.HEADING_2,
children: [
new TextRun({
text: "Date",
bold: true,
size: 40,
}),
],
}),
],
verticalAlign: VerticalAlign.CENTER,
textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM,
}),
new TableCell({
children: [
new Paragraph({
heading: HeadingLevel.HEADING_2,
children: [
new TextRun({
text: "Ticker",
bold: true,
size: 40,
}),
],
}),
],
verticalAlign: VerticalAlign.CENTER,
textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM,
}),
new TableCell({
children: [
new Paragraph({
heading: HeadingLevel.HEADING_2,
children: [
new TextRun({
text: "Price",
bold: true,
size: 40,
}),
],
}),
],
verticalAlign: VerticalAlign.CENTER,
textDirection: TextDirection.TOP_TO_BOTTOM_RIGHT_TO_LEFT,
}),
],
}),
...generateRows(DATA),
],
}),
],
},
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,49 @@
// Simple example to add text to a document
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { AlignmentType, convertMillimetersToTwip, Document, Packer, Paragraph, TextRun } from "../build";
const doc = new Document({
styles: {
paragraphStyles: [
{
id: "test",
name: "Test",
basedOn: "Normal",
next: "Normal",
paragraph: {
indent: { left: convertMillimetersToTwip(6.4) },
},
},
],
},
sections: [
{
properties: {
page: {
margin: {
top: 0,
right: convertMillimetersToTwip(24),
bottom: convertMillimetersToTwip(24),
left: convertMillimetersToTwip(24),
},
},
},
children: [
new Paragraph({
alignment: AlignmentType.THAI_DISTRIBUTE,
children: [
new TextRun({
text: "บริษัทฯ มีเงินสด 41,985.00 บาท และ 25,855.66 บาทตามลำดับ เงินสดทั้งจำนวนอยู่ในความดูแลและรับผิดชอบของกรรมการ บริษัทฯบันทึกการรับชำระเงินและการจ่ายชำระเงินผ่านบัญชีเงินสดเพียงเท่านั้น ซึ่งอาจกระทบต่อความถูกต้องครบถ้วนของการบันทึกบัญชี ทั้งนี้ขึ้นอยู่กับระบบการควบคุมภายในของบริษัท",
size: 28,
}),
],
}),
],
},
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

1416
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -84,7 +84,7 @@
"eslint-plugin-jsdoc": "^39.3.6",
"eslint-plugin-no-null": "^1.0.2",
"eslint-plugin-prefer-arrow": "^1.2.3",
"eslint-plugin-unicorn": "^44.0.0",
"eslint-plugin-unicorn": "^45.0.0",
"glob": "^8.0.1",
"jszip": "^3.1.5",
"mocha": "^10.0.0",
@ -98,7 +98,7 @@
"request-promise": "^4.2.2",
"rimraf": "^3.0.2",
"shelljs": "^0.8.4",
"sinon": "^14.0.0",
"sinon": "^15.0.0",
"stream-browserify": "^3.0.0",
"ts-loader": "^9.0.0",
"ts-node": "^10.2.1",

View File

@ -1,4 +1,5 @@
// http://officeopenxml.com/WPnumbering-numFmt.php
// http://www.datypic.com/sc/ooxml/a-w_val-57.html
import { Attributes, NumberValueElement, XmlAttributeComponent, XmlComponent } from "@file/xml-components";
import { decimalNumber } from "@util/values";
@ -6,21 +7,138 @@ import { AlignmentType } from "../paragraph/formatting";
import { ILevelParagraphStylePropertiesOptions, ParagraphProperties } from "../paragraph/properties";
import { IRunStylePropertiesOptions, RunProperties } from "../paragraph/run/properties";
// TODO: Breaking change - consolidate with number-format
// <xsd:simpleType name="ST_NumberFormat">
// <xsd:restriction base="xsd:string">
// <xsd:enumeration value="decimal"/>
// <xsd:enumeration value="upperRoman"/>
// <xsd:enumeration value="lowerRoman"/>
// <xsd:enumeration value="upperLetter"/>
// <xsd:enumeration value="lowerLetter"/>
// <xsd:enumeration value="ordinal"/>
// <xsd:enumeration value="cardinalText"/>
// <xsd:enumeration value="ordinalText"/>
// <xsd:enumeration value="hex"/>
// <xsd:enumeration value="chicago"/>
// <xsd:enumeration value="ideographDigital"/>
// <xsd:enumeration value="japaneseCounting"/>
// <xsd:enumeration value="aiueo"/>
// <xsd:enumeration value="iroha"/>
// <xsd:enumeration value="decimalFullWidth"/>
// <xsd:enumeration value="decimalHalfWidth"/>
// <xsd:enumeration value="japaneseLegal"/>
// <xsd:enumeration value="japaneseDigitalTenThousand"/>
// <xsd:enumeration value="decimalEnclosedCircle"/>
// <xsd:enumeration value="decimalFullWidth2"/>
// <xsd:enumeration value="aiueoFullWidth"/>
// <xsd:enumeration value="irohaFullWidth"/>
// <xsd:enumeration value="decimalZero"/>
// <xsd:enumeration value="bullet"/>
// <xsd:enumeration value="ganada"/>
// <xsd:enumeration value="chosung"/>
// <xsd:enumeration value="decimalEnclosedFullstop"/>
// <xsd:enumeration value="decimalEnclosedParen"/>
// <xsd:enumeration value="decimalEnclosedCircleChinese"/>
// <xsd:enumeration value="ideographEnclosedCircle"/>
// <xsd:enumeration value="ideographTraditional"/>
// <xsd:enumeration value="ideographZodiac"/>
// <xsd:enumeration value="ideographZodiacTraditional"/>
// <xsd:enumeration value="taiwaneseCounting"/>
// <xsd:enumeration value="ideographLegalTraditional"/>
// <xsd:enumeration value="taiwaneseCountingThousand"/>
// <xsd:enumeration value="taiwaneseDigital"/>
// <xsd:enumeration value="chineseCounting"/>
// <xsd:enumeration value="chineseLegalSimplified"/>
// <xsd:enumeration value="chineseCountingThousand"/>
// <xsd:enumeration value="koreanDigital"/>
// <xsd:enumeration value="koreanCounting"/>
// <xsd:enumeration value="koreanLegal"/>
// <xsd:enumeration value="koreanDigital2"/>
// <xsd:enumeration value="vietnameseCounting"/>
// <xsd:enumeration value="russianLower"/>
// <xsd:enumeration value="russianUpper"/>
// <xsd:enumeration value="none"/>
// <xsd:enumeration value="numberInDash"/>
// <xsd:enumeration value="hebrew1"/>
// <xsd:enumeration value="hebrew2"/>
// <xsd:enumeration value="arabicAlpha"/>
// <xsd:enumeration value="arabicAbjad"/>
// <xsd:enumeration value="hindiVowels"/>
// <xsd:enumeration value="hindiConsonants"/>
// <xsd:enumeration value="hindiNumbers"/>
// <xsd:enumeration value="hindiCounting"/>
// <xsd:enumeration value="thaiLetters"/>
// <xsd:enumeration value="thaiNumbers"/>
// <xsd:enumeration value="thaiCounting"/>
// <xsd:enumeration value="bahtText"/>
// <xsd:enumeration value="dollarText"/>
// <xsd:enumeration value="custom"/>
// </xsd:restriction>
// </xsd:simpleType>
export enum LevelFormat {
BULLET = "bullet",
CARDINAL_TEXT = "cardinalText",
CHICAGO = "chicago",
DECIMAL = "decimal",
UPPER_ROMAN = "upperRoman",
LOWER_ROMAN = "lowerRoman",
UPPER_LETTER = "upperLetter",
LOWER_LETTER = "lowerLetter",
ORDINAL = "ordinal",
CARDINAL_TEXT = "cardinalText",
ORDINAL_TEXT = "ordinalText",
HEX = "hex",
CHICAGO = "chicago",
IDEOGRAPH__DIGITAL = "ideographDigital",
JAPANESE_COUNTING = "japaneseCounting",
AIUEO = "aiueo",
IROHA = "iroha",
DECIMAL_FULL_WIDTH = "decimalFullWidth",
DECIMAL_HALF_WIDTH = "decimalHalfWidth",
JAPANESE_LEGAL = "japaneseLegal",
JAPANESE_DIGITAL_TEN_THOUSAND = "japaneseDigitalTenThousand",
DECIMAL_ENCLOSED_CIRCLE = "decimalEnclosedCircle",
DECIMAL_FULL_WIDTH2 = "decimalFullWidth2",
AIUEO_FULL_WIDTH = "aiueoFullWidth",
IROHA_FULL_WIDTH = "irohaFullWidth",
DECIMAL_ZERO = "decimalZero",
BULLET = "bullet",
GANADA = "ganada",
CHOSUNG = "chosung",
DECIMAL_ENCLOSED_FULLSTOP = "decimalEnclosedFullstop",
DECIMAL_ENCLOSED_PARENTHESES = "decimalEnclosedParen",
DECIMAL_ZERO = "decimalZero",
LOWER_LETTER = "lowerLetter",
LOWER_ROMAN = "lowerRoman",
DECIMAL_ENCLOSED_CIRCLE_CHINESE = "decimalEnclosedCircleChinese",
IDEOGRAPH_ENCLOSED_CIRCLE = "ideographEnclosedCircle",
IDEOGRAPH_TRADITIONAL = "ideographTraditional",
IDEOGRAPH_ZODIAC = "ideographZodiac",
IDEOGRAPH_ZODIAC_TRADITIONAL = "ideographZodiacTraditional",
TAIWANESE_COUNTING = "taiwaneseCounting",
IDEOGRAPH_LEGAL_TRADITIONAL = "ideographLegalTraditional",
TAIWANESE_COUNTING_THOUSAND = "taiwaneseCountingThousand",
TAIWANESE_DIGITAL = "taiwaneseDigital",
CHINESE_COUNTING = "chineseCounting",
CHINESE_LEGAL_SIMPLIFIED = "chineseLegalSimplified",
CHINESE_COUNTING_THOUSAND = "chineseCountingThousand",
KOREAN_DIGITAL = "koreanDigital",
KOREAN_COUNTING = "koreanCounting",
KOREAN_LEGAL = "koreanLegal",
KOREAN_DIGITAL2 = "koreanDigital2",
VIETNAMESE_COUNTING = "vietnameseCounting",
RUSSIAN_LOWER = "russianLower",
RUSSIAN_UPPER = "russianUpper",
NONE = "none",
ORDINAL_TEXT = "ordinalText",
UPPER_LETTER = "upperLetter",
UPPER_ROMAN = "upperRoman",
NUMBER_IN_DASH = "numberInDash",
HEBREW1 = "hebrew1",
HEBREW2 = "hebrew2",
ARABIC_ALPHA = "arabicAlpha",
ARABIC_ABJAD = "arabicAbjad",
HINDI_VOWELS = "hindiVowels",
HINDI_CONSONANTS = "hindiConsonants",
HINDI_NUMBERS = "hindiNumbers",
HINDI_COUNTING = "hindiCounting",
THAI_LETTERS = "thaiLetters",
THAI_NUMBERS = "thaiNumbers",
THAI_COUNTING = "thaiCounting",
BAHT_TEXT = "bahtText",
DOLLAR_TEXT = "dollarText",
CUSTOM = "custom",
}
class LevelAttributes extends XmlAttributeComponent<{

View File

@ -1,6 +1,7 @@
import { expect } from "chai";
import { Formatter } from "@export/formatter";
import { SpaceType } from "@file/shared";
import { Text } from "./text";
@ -13,5 +14,26 @@ describe("Text", () => {
"w:t": [{ _attr: { "xml:space": "preserve" } }, " this is\n text"],
});
});
it("adds the passed in text to the component with options", () => {
const t = new Text({
text: " this is\n text",
space: SpaceType.PRESERVE,
});
const f = new Formatter().format(t);
expect(f).to.deep.equal({
"w:t": [{ _attr: { "xml:space": "preserve" } }, " this is\n text"],
});
});
it("adds the passed in text to the component with options and sets default space type", () => {
const t = new Text({
text: " this is\n text",
});
const f = new Formatter().format(t);
expect(f).to.deep.equal({
"w:t": [{ _attr: { "xml:space": "default" } }, " this is\n text"],
});
});
});
});

View File

@ -3,11 +3,31 @@ import { XmlComponent } from "@file/xml-components";
import { TextAttributes } from "../text-attributes";
export class Text extends XmlComponent {
public constructor(text: string) {
super("w:t");
this.root.push(new TextAttributes({ space: SpaceType.PRESERVE }));
// <xsd:complexType name="CT_Text">
// <xsd:simpleContent>
// <xsd:extension base="s:ST_String">
// <xsd:attribute ref="xml:space" use="optional" />
// </xsd:extension>
// </xsd:simpleContent>
// </xsd:complexType>
this.root.push(text);
interface ITextOptions {
readonly space?: SpaceType;
readonly text?: string;
}
export class Text extends XmlComponent {
public constructor(options: string | ITextOptions) {
super("w:t");
if (typeof options === "string") {
this.root.push(new TextAttributes({ space: SpaceType.PRESERVE }));
this.root.push(options);
return;
} else {
this.root.push(new TextAttributes({ space: options.space ?? SpaceType.DEFAULT }));
this.root.push(options.text);
return;
}
}
}

View File

@ -19,6 +19,7 @@ export enum UnderlineType {
WAVE = "wave",
WAVYHEAVY = "wavyHeavy",
WAVYDOUBLE = "wavyDouble",
NONE = "none",
}
export class Underline extends XmlComponent {