Add language support
This commit is contained in:
69
demo/83-setting-languages.ts
Normal file
69
demo/83-setting-languages.ts
Normal file
@ -0,0 +1,69 @@
|
||||
// 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 { Document, Packer, Paragraph } from "../build";
|
||||
|
||||
const doc = new Document({
|
||||
styles: {
|
||||
default: {
|
||||
document: {
|
||||
run: {
|
||||
color: "ff0000",
|
||||
language: {
|
||||
value: "es-ES",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
paragraphStyles: [
|
||||
{
|
||||
id: "frenchNormal",
|
||||
name: "French Normal",
|
||||
basedOn: "Normal",
|
||||
next: "Normal",
|
||||
run: {
|
||||
color: "999999",
|
||||
italics: true,
|
||||
language: {
|
||||
value: "fr-FR",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "koreanNormal",
|
||||
name: "Korean Normal",
|
||||
basedOn: "Normal",
|
||||
next: "Normal",
|
||||
run: {
|
||||
color: "0000ff",
|
||||
bold: true,
|
||||
language: {
|
||||
value: "ko-KR",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
sections: [
|
||||
{
|
||||
properties: {},
|
||||
children: [
|
||||
new Paragraph({
|
||||
text: "Yo vivo en Granada, una ciudad pequeña que tiene monumentos muy importantes como la Alhambra. Aquí la comida es deliciosa y son famosos el gazpacho, el rebujito y el salmorejo.",
|
||||
}),
|
||||
new Paragraph({
|
||||
text: "Toute personne a droit à l'éducation. L'éducation doit être gratuite, au moins en ce qui concerne l'enseignement élémentaire et fondamental. L'enseignement élémentaire est obligatoire. L'enseignement technique et professionnel doit être généralisé; l'accès aux études supérieures doit être ouvert en pleine égalité à tous en fonction de leur mérite.",
|
||||
style: "frenchNormal",
|
||||
}),
|
||||
new Paragraph({
|
||||
text: "대법관은 대법원장의 제청으로 국회의 동의를 얻어 대통령이 임명한다. 강화조약. 국가는 국민 모두의 생산 및 생활의 기반이 되는 국토의 효율적이고 균형있는 이용·개발과 보전을 위하여 법률이 정하는 바에 의하여 그에 관한 필요한 제한과 의무를 과할 수 있다, 국가는 청원에 대하여 심사할 의무를 진다.",
|
||||
style: "koreanNormal",
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Packer.toBuffer(doc).then((buffer) => {
|
||||
fs.writeFileSync("My Document.docx", buffer);
|
||||
});
|
29
src/file/paragraph/run/language.spec.ts
Normal file
29
src/file/paragraph/run/language.spec.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "@export/formatter";
|
||||
|
||||
import { createLanguageComponent } from "./language";
|
||||
|
||||
describe("Language", () => {
|
||||
describe("#createLanguageComponent", () => {
|
||||
it("should create a language component", () => {
|
||||
const tree = new Formatter().format(
|
||||
createLanguageComponent({
|
||||
value: "en-US",
|
||||
eastAsia: "zh-CN",
|
||||
bidirectional: "ar-SA",
|
||||
}),
|
||||
);
|
||||
|
||||
expect(tree).to.deep.equal({
|
||||
"w:lang": {
|
||||
_attr: {
|
||||
"w:bidi": "ar-SA",
|
||||
"w:eastAsia": "zh-CN",
|
||||
"w:val": "en-US",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
35
src/file/paragraph/run/language.ts
Normal file
35
src/file/paragraph/run/language.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { BuilderElement, XmlComponent } from "@file/xml-components";
|
||||
|
||||
// <xsd:complexType name="CT_Language">
|
||||
// <xsd:attribute name="val" type="s:ST_Lang" use="optional"/>
|
||||
// <xsd:attribute name="eastAsia" type="s:ST_Lang" use="optional"/>
|
||||
// <xsd:attribute name="bidi" type="s:ST_Lang" use="optional"/>
|
||||
// </xsd:complexType>
|
||||
export interface ILanguageOptions {
|
||||
readonly value?: string;
|
||||
readonly eastAsia?: string;
|
||||
readonly bidirectional?: string;
|
||||
}
|
||||
|
||||
export const createLanguageComponent = (options: ILanguageOptions): XmlComponent =>
|
||||
new BuilderElement<{
|
||||
readonly value?: string;
|
||||
readonly eastAsia?: string;
|
||||
readonly bidirectional?: string;
|
||||
}>({
|
||||
name: "w:lang",
|
||||
attributes: {
|
||||
value: {
|
||||
key: "w:val",
|
||||
value: options.value,
|
||||
},
|
||||
eastAsia: {
|
||||
key: "w:eastAsia",
|
||||
value: options.eastAsia,
|
||||
},
|
||||
bidirectional: {
|
||||
key: "w:bidi",
|
||||
value: options.bidirectional,
|
||||
},
|
||||
},
|
||||
});
|
@ -2,7 +2,6 @@ import { BorderElement, IBorderOptions } from "@file/border";
|
||||
import { IShadingAttributesProperties, Shading } from "@file/shading";
|
||||
import { ChangeAttributes, IChangedAttributesProperties } from "@file/track-revision/track-revision";
|
||||
import {
|
||||
BuilderElement,
|
||||
HpsMeasureElement,
|
||||
IgnoreIfEmptyXmlComponent,
|
||||
NumberValueElement,
|
||||
@ -13,6 +12,7 @@ import {
|
||||
|
||||
import { EmphasisMark, EmphasisMarkType } from "./emphasis-mark";
|
||||
import { CharacterSpacing, Color, Highlight, HighlightComplexScript } from "./formatting";
|
||||
import { createLanguageComponent, ILanguageOptions } from "./language";
|
||||
import { IFontAttributesProperties, RunFonts } from "./run-fonts";
|
||||
import { SubScript, SuperScript } from "./script";
|
||||
import { Underline, UnderlineType } from "./underline";
|
||||
@ -52,16 +52,7 @@ export interface IRunStylePropertiesOptions {
|
||||
readonly emboss?: boolean;
|
||||
readonly imprint?: boolean;
|
||||
readonly revision?: IRunPropertiesChangeOptions;
|
||||
// <xsd:complexType name="CT_Language">
|
||||
// <xsd:attribute name="val" type="s:ST_Lang" use="optional"/>
|
||||
// <xsd:attribute name="eastAsia" type="s:ST_Lang" use="optional"/>
|
||||
// <xsd:attribute name="bidi" type="s:ST_Lang" use="optional"/>
|
||||
// </xsd:complexType>
|
||||
readonly language?: {
|
||||
readonly value?: string;
|
||||
readonly eastAsia?: string;
|
||||
readonly bidirectional?: string;
|
||||
};
|
||||
readonly language?: ILanguageOptions;
|
||||
readonly border?: IBorderOptions;
|
||||
readonly vanish?: boolean;
|
||||
readonly specVanish?: boolean;
|
||||
@ -253,29 +244,7 @@ export class RunProperties extends IgnoreIfEmptyXmlComponent {
|
||||
}
|
||||
|
||||
if (options.language) {
|
||||
this.push(
|
||||
new BuilderElement<{
|
||||
readonly value: string;
|
||||
readonly eastAsia: string;
|
||||
readonly bidirectional: string;
|
||||
}>({
|
||||
name: "w:lang",
|
||||
attributes: {
|
||||
value: {
|
||||
key: "w:val",
|
||||
value: options.language.value,
|
||||
},
|
||||
eastAsia: {
|
||||
key: "w:eastAsia",
|
||||
value: options.language.eastAsia,
|
||||
},
|
||||
bidirectional: {
|
||||
key: "w:bidi",
|
||||
value: options.language.bidirectional,
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
this.push(createLanguageComponent(options.language));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,10 @@
|
||||
import { BaseXmlComponent, IContext } from "./base";
|
||||
import { IXmlableObject } from "./xmlable-object";
|
||||
import { IXmlableObject, IXmlAttribute } from "./xmlable-object";
|
||||
|
||||
export type AttributeMap<T> = { readonly [P in keyof T]: string };
|
||||
|
||||
export type AttributeData = { readonly [key: string]: boolean | number | string };
|
||||
export type AttributePayload<T extends AttributeData> = Record<
|
||||
keyof T,
|
||||
{
|
||||
readonly key: string;
|
||||
readonly value?: T[keyof T];
|
||||
}
|
||||
>;
|
||||
export type AttributePayload<T> = { readonly [P in keyof T]: { readonly key: string; readonly value: T[P] } };
|
||||
|
||||
export abstract class XmlAttributeComponent<T extends object> extends BaseXmlComponent {
|
||||
protected readonly xmlKeys?: AttributeMap<T>;
|
||||
@ -39,13 +33,9 @@ export class NextAttributeComponent<T extends AttributeData> extends BaseXmlComp
|
||||
}
|
||||
|
||||
public prepForXml(_: IContext): IXmlableObject {
|
||||
const attrs = {};
|
||||
Object.values(this.root).forEach(({ key, value }) => {
|
||||
if (value !== undefined) {
|
||||
// eslint-disable-next-line functional/immutable-data
|
||||
attrs[key] = value;
|
||||
}
|
||||
});
|
||||
const attrs = Object.values<{ readonly key: string; readonly value: string | boolean | number }>(this.root)
|
||||
.filter(({ value }) => !!value)
|
||||
.reduce((acc, { key, value }) => ({ ...acc, [key]: value }), {} as IXmlAttribute);
|
||||
return { _attr: attrs };
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,11 @@ export class StringContainer extends XmlComponent {
|
||||
}
|
||||
|
||||
export class BuilderElement<T extends AttributeData> extends XmlComponent {
|
||||
public constructor(options: { readonly attributes?: AttributePayload<T>; readonly name: string }) {
|
||||
public constructor(options: {
|
||||
readonly name: string;
|
||||
readonly attributes?: AttributePayload<T>;
|
||||
readonly children?: readonly XmlComponent[];
|
||||
}) {
|
||||
super(options.name);
|
||||
|
||||
if (options.attributes) {
|
||||
|
Reference in New Issue
Block a user