20231016:basic font guessing and putText
function
- issues : the CJK font can't be in .ttc format. (upstream-problem)
This commit is contained in:
parent
421f335d53
commit
a37fd632a7
11 changed files with 6909 additions and 1033 deletions
|
@ -27,3 +27,5 @@ License: MIT
|
||||||
- 20231006: tîng siá parser, using `ts-parsec`.
|
- 20231006: tîng siá parser, using `ts-parsec`.
|
||||||
- 20231010: 初步完成tsit ê階段ê Parser`。
|
- 20231010: 初步完成tsit ê階段ê Parser`。
|
||||||
- 20231012: clo->js converter successfully (maybe.)
|
- 20231012: clo->js converter successfully (maybe.)
|
||||||
|
- 20231016:basic font guessing and `putText` function
|
||||||
|
- issues : the CJK font can't be in .ttc format. (upstream-problem)
|
7633
package-lock.json
generated
7633
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -41,7 +41,7 @@
|
||||||
"harfbuzzjs": "^0.3.3",
|
"harfbuzzjs": "^0.3.3",
|
||||||
"js-tokens": "^8.0.2",
|
"js-tokens": "^8.0.2",
|
||||||
"minimist": "^1.2.8",
|
"minimist": "^1.2.8",
|
||||||
"npx": "^3.0.0",
|
"npx": "^10.2.2",
|
||||||
"pdf-lib": "^1.17.1",
|
"pdf-lib": "^1.17.1",
|
||||||
"typescript-parsec": "^0.3.4"
|
"typescript-parsec": "^0.3.4"
|
||||||
}
|
}
|
||||||
|
|
141
src/canva.ts
Normal file
141
src/canva.ts
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
const { execSync } = require('child_process');
|
||||||
|
import { PDFDocument, RGB, ColorTypes } from "pdf-lib";
|
||||||
|
import { readFileSync, writeFileSync } from "fs";
|
||||||
|
import fontkit from '@pdf-lib/fontkit';
|
||||||
|
|
||||||
|
|
||||||
|
export interface CloCommand {
|
||||||
|
cmdName : string,
|
||||||
|
args : TextStreamUnit[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TextStreamUnit = string | CloCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a clo document
|
||||||
|
*/
|
||||||
|
export interface Clo{
|
||||||
|
mainText : TextStreamUnit[],
|
||||||
|
mainFontStyle? : FontStyle,
|
||||||
|
PDFCanvas : PDFDocument,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Font Style Interface
|
||||||
|
* name : eg. "FreeSans"
|
||||||
|
* size : in px, not in pt.
|
||||||
|
* textWeight : TextWeight.REGULAR ,etc
|
||||||
|
* textWeight : TextStyle.ITALIC ,etc
|
||||||
|
*/
|
||||||
|
export interface FontStyle{
|
||||||
|
name : string,
|
||||||
|
size : number,
|
||||||
|
textWeight : TextWeight,
|
||||||
|
textStyle : TextStyle,
|
||||||
|
color? : string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum TextWeight {
|
||||||
|
REGULAR,
|
||||||
|
BOLD,
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum TextStyle{
|
||||||
|
NORMAL,
|
||||||
|
ITALIC,
|
||||||
|
OBLIQUE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* guess the font path of a font style with fontconfig's commands
|
||||||
|
* @param style the font style
|
||||||
|
* @returns the font path in string, if found none or .ttc, return a empty string.
|
||||||
|
*/
|
||||||
|
export function fontStyleTofontPath(style : FontStyle) : string{
|
||||||
|
try {
|
||||||
|
let fcMatchOut = execSync(
|
||||||
|
`fc-match "${style.name}":${TextWeight[style.textWeight]}:`+
|
||||||
|
`${TextStyle[style.textStyle]}`);
|
||||||
|
|
||||||
|
let fontFileName : string = fcMatchOut.toString().match(/^[^:]+/g)[0];
|
||||||
|
|
||||||
|
if (fontFileName.match(/[.]ttc$/g)){
|
||||||
|
console.log("WARNING: the program doesn't support .ttc font format!\n"+
|
||||||
|
"Font file name: "+
|
||||||
|
fontFileName);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
let fcListOut = execSync(
|
||||||
|
`fc-list | grep ${fontFileName}`);
|
||||||
|
let fontPath : string = fcListOut.toString().match(/^[^:]+/g)[0];
|
||||||
|
return fontPath;
|
||||||
|
} catch (error) {
|
||||||
|
console.log("WARNING: You should install `fontconfig` to select the font.");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function hexToRGB(hex : string) : RGB{
|
||||||
|
let matched = hex.match(/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);
|
||||||
|
|
||||||
|
var result : RGB ;
|
||||||
|
if (!matched){
|
||||||
|
console.log("WARNING: the hex color code is not valid. set to #000000")
|
||||||
|
result = {
|
||||||
|
type : ColorTypes.RGB,
|
||||||
|
red: 0,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
result = {
|
||||||
|
type : ColorTypes.RGB,
|
||||||
|
red: parseInt(matched[1], 16),
|
||||||
|
green: parseInt(matched[2], 16),
|
||||||
|
blue: parseInt(matched[3], 16)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* put text in a clo canva.
|
||||||
|
* @param clo : the clo object
|
||||||
|
* @param str input string
|
||||||
|
* @param sty input fontstyle
|
||||||
|
* @param PageNo : the input page, 0-indexed.
|
||||||
|
* @param x base x-point from left
|
||||||
|
* @param y base y-point from top
|
||||||
|
* @returns a new updated clo object
|
||||||
|
*/
|
||||||
|
export async function putText(clo : Clo, str : string, sty : FontStyle,
|
||||||
|
pageNo : number, x : number, y : number): Promise<Clo>{
|
||||||
|
|
||||||
|
clo.PDFCanvas.registerFontkit(fontkit);
|
||||||
|
let canvaPage = clo.PDFCanvas.getPage(pageNo);
|
||||||
|
|
||||||
|
|
||||||
|
const fontBytes = readFileSync(fontStyleTofontPath(sty));
|
||||||
|
const fontEmbed = await clo.PDFCanvas.embedFont(fontBytes);
|
||||||
|
|
||||||
|
var textColor : RGB;
|
||||||
|
if (sty.color === undefined){
|
||||||
|
textColor = hexToRGB("#000000");
|
||||||
|
}else{
|
||||||
|
textColor = hexToRGB(sty.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
let drawTextOptions = {
|
||||||
|
x : x,
|
||||||
|
y : canvaPage.getHeight() - y,
|
||||||
|
font : fontEmbed,
|
||||||
|
size : sty.size,
|
||||||
|
color : textColor};
|
||||||
|
|
||||||
|
canvaPage.drawText(str, drawTextOptions);
|
||||||
|
|
||||||
|
return clo;
|
||||||
|
};
|
|
@ -37,6 +37,10 @@ INPUT_FILE\tan input .clo file
|
||||||
## Parameters
|
## Parameters
|
||||||
---
|
---
|
||||||
--output-js\tgenerated the output middle JS file
|
--output-js\tgenerated the output middle JS file
|
||||||
|
|
||||||
|
|
||||||
|
Report bugs to: clo@kianting.info
|
||||||
|
clo home page: <https://kianting.info/wiki/w/Project:Clo>
|
||||||
`;
|
`;
|
||||||
processArgv(argv, helpDesc);
|
processArgv(argv, helpDesc);
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,7 +26,8 @@ function pdfGenerate() {
|
||||||
page.drawText("x:20, y:100 天地人", { x: 20, y: 100, font: font2 });
|
page.drawText("x:20, y:100 天地人", { x: 20, y: 100, font: font2 });
|
||||||
page.drawText("عربي", { x: 50, y: 150, font: font3 });
|
page.drawText("عربي", { x: 50, y: 150, font: font3 });
|
||||||
const pdfBytes = yield pdfDoc.save();
|
const pdfBytes = yield pdfDoc.save();
|
||||||
(0, fs_1.writeFileSync)('/tmp/test.pdf', pdfBytes);
|
(0, fs_1.writeFileSync)('/tmp/test2.pdf', pdfBytes);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.pdfGenerate = pdfGenerate;
|
exports.pdfGenerate = pdfGenerate;
|
||||||
|
pdfGenerate();
|
||||||
|
|
|
@ -21,5 +21,7 @@ export async function pdfGenerate(){
|
||||||
|
|
||||||
const pdfBytes = await pdfDoc.save();
|
const pdfBytes = await pdfDoc.save();
|
||||||
|
|
||||||
writeFileSync('/tmp/test.pdf', pdfBytes);
|
writeFileSync('/tmp/test2.pdf', pdfBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pdfGenerate();
|
86
tests/index.d.ts
vendored
86
tests/index.d.ts
vendored
|
@ -1,86 +0,0 @@
|
||||||
declare let assert: any;
|
|
||||||
declare let tokenize: any;
|
|
||||||
declare let a: any;
|
|
||||||
declare let example1: any;
|
|
||||||
declare let example2: any;
|
|
||||||
declare let thenDo: any;
|
|
||||||
declare let orDo: any;
|
|
||||||
declare let zeroOrMoreDo: any;
|
|
||||||
declare let notDo: any;
|
|
||||||
declare let matchAny: any;
|
|
||||||
declare let compPart1: any;
|
|
||||||
declare let compPart2: any;
|
|
||||||
declare let doThenTestee1: {
|
|
||||||
_tag: string;
|
|
||||||
value: {
|
|
||||||
matched: string;
|
|
||||||
remained: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
declare let doTestRes1: any;
|
|
||||||
declare let doThenTestee2: {
|
|
||||||
_tag: string;
|
|
||||||
value: {
|
|
||||||
matched: string;
|
|
||||||
remained: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
declare let doTestRes2: any;
|
|
||||||
declare let doThenTestee3: {
|
|
||||||
_tag: string;
|
|
||||||
value: {
|
|
||||||
matched: string;
|
|
||||||
remained: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
declare let doTestRes3: any;
|
|
||||||
declare let doThenTestee4: {
|
|
||||||
_tag: string;
|
|
||||||
value: {
|
|
||||||
matched: string;
|
|
||||||
remained: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
declare let doTestRes4: any;
|
|
||||||
declare let doThenTestee5: {
|
|
||||||
_tag: string;
|
|
||||||
value: {
|
|
||||||
matched: string;
|
|
||||||
remained: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
declare let doTestRes5: any;
|
|
||||||
declare let doThenTestee6: {
|
|
||||||
_tag: string;
|
|
||||||
value: {
|
|
||||||
matched: string;
|
|
||||||
remained: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
declare let doTestRes6: any;
|
|
||||||
declare let doThenTestee7: {
|
|
||||||
_tag: string;
|
|
||||||
value: {
|
|
||||||
matched: string;
|
|
||||||
remained: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
declare let doTestRes7: any;
|
|
||||||
declare let doThenTestee8: {
|
|
||||||
_tag: string;
|
|
||||||
value: {
|
|
||||||
matched: string;
|
|
||||||
remained: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
declare let doTestRes8: any;
|
|
||||||
declare let doThenTestee9: {
|
|
||||||
_tag: string;
|
|
||||||
value: {
|
|
||||||
matched: string;
|
|
||||||
remained: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
declare let doTestRes9: any;
|
|
||||||
declare let harfbuzz: any;
|
|
||||||
declare let pdfManipulate: any;
|
|
|
@ -1,95 +0,0 @@
|
||||||
"use strict";
|
|
||||||
let assert = require("assert");
|
|
||||||
let tokenize = require("../src/tokenize");
|
|
||||||
let a = tokenize.match1Char("我");
|
|
||||||
let example1 = a({ matched: "", remained: "我的" });
|
|
||||||
assert(example1._tag == "Some");
|
|
||||||
assert(example1.value.matched == "我");
|
|
||||||
assert(example1.value.remained == "的");
|
|
||||||
let example2 = a({ matched: "", remained: "妳的" });
|
|
||||||
assert(example2._tag == "None");
|
|
||||||
let thenDo = tokenize.thenDo;
|
|
||||||
let orDo = tokenize.orDo;
|
|
||||||
let zeroOrMoreDo = tokenize.zeroOrMoreDo;
|
|
||||||
let notDo = tokenize.notDo;
|
|
||||||
let matchAny = tokenize.matchAny;
|
|
||||||
// composed part x
|
|
||||||
let compPart1 = tokenize.match1Char("我");
|
|
||||||
let compPart2 = tokenize.match1Char("的");
|
|
||||||
let doThenTestee1 = { _tag: "Some", value: { matched: "", remained: "我的貓" } };
|
|
||||||
let doTestRes1 = thenDo(thenDo(doThenTestee1, compPart1), compPart2);
|
|
||||||
assert(doTestRes1._tag == "Some");
|
|
||||||
assert(doTestRes1.value.matched == "我的");
|
|
||||||
assert(doTestRes1.value.remained == "貓");
|
|
||||||
let doThenTestee2 = { _tag: "Some", value: { matched: "", remained: "我們" } };
|
|
||||||
let doTestRes2 = thenDo(thenDo(doThenTestee2, compPart1), compPart2);
|
|
||||||
assert(doTestRes2._tag == "None");
|
|
||||||
let doThenTestee3 = { _tag: "Some", value: { matched: "", remained: "我的貓" } };
|
|
||||||
let doTestRes3 = thenDo(thenDo(doThenTestee3, orDo(compPart1, compPart2)), compPart2);
|
|
||||||
assert(doTestRes3._tag == "Some");
|
|
||||||
assert(doTestRes3.value.matched == "我的");
|
|
||||||
assert(doTestRes3.value.remained == "貓");
|
|
||||||
let doThenTestee4 = { _tag: "Some", value: { matched: "", remained: "的的貓" } };
|
|
||||||
let doTestRes4 = thenDo(thenDo(doThenTestee4, orDo(compPart1, compPart2)), compPart2);
|
|
||||||
assert(doTestRes4._tag == "Some");
|
|
||||||
assert(doTestRes4.value.matched == "的的");
|
|
||||||
assert(doTestRes4.value.remained == "貓");
|
|
||||||
let doThenTestee5 = { _tag: "Some", value: { matched: "", remained: "的貓" } };
|
|
||||||
let doTestRes5 = thenDo(thenDo(doThenTestee5, zeroOrMoreDo(compPart1)), compPart2);
|
|
||||||
assert(doTestRes5._tag == "Some");
|
|
||||||
assert(doTestRes5.value.matched == "的");
|
|
||||||
assert(doTestRes5.value.remained == "貓");
|
|
||||||
let doThenTestee6 = { _tag: "Some", value: { matched: "", remained: "我我我的貓" } };
|
|
||||||
let doTestRes6 = thenDo(thenDo(doThenTestee6, zeroOrMoreDo(compPart1)), compPart2);
|
|
||||||
assert(doTestRes6._tag == "Some");
|
|
||||||
assert(doTestRes6.value.matched == "我我我的");
|
|
||||||
assert(doTestRes6.value.remained == "貓");
|
|
||||||
let doThenTestee7 = { _tag: "Some", value: { matched: "", remained: "我的" } };
|
|
||||||
let doTestRes7 = thenDo(thenDo(doThenTestee7, notDo(compPart1)), compPart2);
|
|
||||||
assert(doTestRes7._tag == "None");
|
|
||||||
let doThenTestee8 = { _tag: "Some", value: { matched: "", remained: "妳的" } };
|
|
||||||
let doTestRes8 = thenDo(thenDo(doThenTestee8, notDo(compPart1)), compPart2);
|
|
||||||
assert(doTestRes8._tag == "Some");
|
|
||||||
assert(doTestRes8.value.matched == "妳的");
|
|
||||||
let doThenTestee9 = { _tag: "Some", value: { matched: "", remained: "妳的" } };
|
|
||||||
let doTestRes9 = thenDo(doThenTestee9, matchAny);
|
|
||||||
assert(doTestRes9._tag == "Some");
|
|
||||||
assert(doTestRes9.value.matched == "妳");
|
|
||||||
assert(doTestRes9.value.remained == "的");
|
|
||||||
tokenize.tokenize("+123");
|
|
||||||
tokenize.tokenize("123");
|
|
||||||
tokenize.tokenize("-123");
|
|
||||||
tokenize.tokenize(" 123");
|
|
||||||
try {
|
|
||||||
tokenize.tokenize("c123");
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
tokenize.tokenize(" ");
|
|
||||||
tokenize.tokenize(" ");
|
|
||||||
tokenize.tokenize(" \t");
|
|
||||||
tokenize.tokenize(" \t123");
|
|
||||||
try {
|
|
||||||
tokenize.tokenize(" \t123aaa456");
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
tokenize.tokenize(" \t123\n456");
|
|
||||||
tokenize.tokenize("\"\"");
|
|
||||||
tokenize.tokenize("\"123\"");
|
|
||||||
tokenize.tokenize("\"1\\\"23\"");
|
|
||||||
tokenize.tokenize("\"1\\\"23\" abc123");
|
|
||||||
tokenize.tokenize("+0.012");
|
|
||||||
tokenize.tokenize("0.0");
|
|
||||||
tokenize.tokenize("-222.0");
|
|
||||||
tokenize.tokenize("1+1 ==2; 3+8 foo(12)");
|
|
||||||
console.log(tokenize.tokenize("2+2"));
|
|
||||||
// harfbuzz test
|
|
||||||
let harfbuzz = require("../src/harfbuzz.js");
|
|
||||||
harfbuzz.harfbuzzTest("123.abc");
|
|
||||||
// pdf test
|
|
||||||
let pdfManipulate = require("../src/pdfManipulate.js");
|
|
||||||
pdfManipulate.pdfGenerate("123.abc");
|
|
||||||
console.log("/tmp/test.pdf產出ah");
|
|
122
tests/index.ts
122
tests/index.ts
|
@ -1,122 +0,0 @@
|
||||||
|
|
||||||
let assert = require("assert");
|
|
||||||
let tokenize = require("../src/tokenize");
|
|
||||||
|
|
||||||
let a = tokenize.match1Char("我");
|
|
||||||
|
|
||||||
let example1 = a({matched: "", remained: "我的"});
|
|
||||||
assert(example1._tag == "Some");
|
|
||||||
assert(example1.value.matched == "我");
|
|
||||||
assert(example1.value.remained == "的");
|
|
||||||
|
|
||||||
let example2 = a({matched: "", remained: "妳的"});
|
|
||||||
assert(example2._tag == "None");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let thenDo = tokenize.thenDo;
|
|
||||||
let orDo = tokenize.orDo;
|
|
||||||
let zeroOrMoreDo = tokenize.zeroOrMoreDo;
|
|
||||||
let notDo = tokenize.notDo;
|
|
||||||
let matchAny = tokenize.matchAny;
|
|
||||||
|
|
||||||
// composed part x
|
|
||||||
let compPart1 = tokenize.match1Char("我");
|
|
||||||
let compPart2 = tokenize.match1Char("的");
|
|
||||||
|
|
||||||
let doThenTestee1 = {_tag : "Some",value : {matched: "", remained: "我的貓"}};
|
|
||||||
let doTestRes1 = thenDo(thenDo(doThenTestee1, compPart1), compPart2);
|
|
||||||
assert(doTestRes1._tag == "Some");
|
|
||||||
assert(doTestRes1.value.matched == "我的");
|
|
||||||
assert(doTestRes1.value.remained == "貓");
|
|
||||||
|
|
||||||
|
|
||||||
let doThenTestee2 = {_tag : "Some",value : {matched: "", remained: "我們"}};
|
|
||||||
let doTestRes2 = thenDo(thenDo(doThenTestee2, compPart1), compPart2);
|
|
||||||
assert(doTestRes2._tag == "None");
|
|
||||||
|
|
||||||
let doThenTestee3 = {_tag : "Some",value : {matched: "", remained: "我的貓"}};
|
|
||||||
let doTestRes3 = thenDo(thenDo(doThenTestee3, orDo(compPart1, compPart2)), compPart2);
|
|
||||||
assert(doTestRes3._tag == "Some");
|
|
||||||
assert(doTestRes3.value.matched == "我的");
|
|
||||||
assert(doTestRes3.value.remained == "貓");
|
|
||||||
|
|
||||||
let doThenTestee4 = {_tag : "Some",value : {matched: "", remained: "的的貓"}};
|
|
||||||
let doTestRes4 = thenDo(thenDo(doThenTestee4, orDo(compPart1, compPart2)), compPart2);
|
|
||||||
assert(doTestRes4._tag == "Some");
|
|
||||||
assert(doTestRes4.value.matched == "的的");
|
|
||||||
assert(doTestRes4.value.remained == "貓");
|
|
||||||
|
|
||||||
let doThenTestee5 = {_tag : "Some",value : {matched: "", remained: "的貓"}};
|
|
||||||
let doTestRes5 = thenDo(thenDo(doThenTestee5, zeroOrMoreDo(compPart1)), compPart2);
|
|
||||||
assert(doTestRes5._tag == "Some");
|
|
||||||
assert(doTestRes5.value.matched == "的");
|
|
||||||
assert(doTestRes5.value.remained == "貓");
|
|
||||||
|
|
||||||
let doThenTestee6 = {_tag : "Some",value : {matched: "", remained: "我我我的貓"}};
|
|
||||||
let doTestRes6 = thenDo(thenDo(doThenTestee6, zeroOrMoreDo(compPart1)), compPart2);
|
|
||||||
assert(doTestRes6._tag == "Some");
|
|
||||||
assert(doTestRes6.value.matched == "我我我的");
|
|
||||||
assert(doTestRes6.value.remained == "貓");
|
|
||||||
|
|
||||||
let doThenTestee7 = {_tag : "Some",value : {matched: "", remained: "我的"}};
|
|
||||||
let doTestRes7 = thenDo(thenDo(doThenTestee7, notDo(compPart1)), compPart2);
|
|
||||||
assert(doTestRes7._tag == "None");
|
|
||||||
|
|
||||||
let doThenTestee8 = {_tag : "Some",value : {matched: "", remained: "妳的"}};
|
|
||||||
let doTestRes8 = thenDo(thenDo(doThenTestee8, notDo(compPart1)), compPart2);
|
|
||||||
assert(doTestRes8._tag == "Some");
|
|
||||||
assert(doTestRes8.value.matched == "妳的");
|
|
||||||
|
|
||||||
let doThenTestee9 = {_tag : "Some",value : {matched: "", remained: "妳的"}};
|
|
||||||
let doTestRes9 = thenDo(doThenTestee9, matchAny);
|
|
||||||
assert(doTestRes9._tag == "Some");
|
|
||||||
assert(doTestRes9.value.matched == "妳");
|
|
||||||
assert(doTestRes9.value.remained == "的");
|
|
||||||
|
|
||||||
tokenize.tokenize("+123");
|
|
||||||
tokenize.tokenize("123");
|
|
||||||
tokenize.tokenize("-123");
|
|
||||||
tokenize.tokenize(" 123");
|
|
||||||
try {
|
|
||||||
tokenize.tokenize("c123");
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
tokenize.tokenize(" ");
|
|
||||||
tokenize.tokenize(" ");
|
|
||||||
tokenize.tokenize(" \t");
|
|
||||||
tokenize.tokenize(" \t123");
|
|
||||||
|
|
||||||
try {
|
|
||||||
tokenize.tokenize(" \t123aaa456");
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
tokenize.tokenize(" \t123\n456");
|
|
||||||
|
|
||||||
tokenize.tokenize("\"\"");
|
|
||||||
tokenize.tokenize("\"123\"");
|
|
||||||
tokenize.tokenize("\"1\\\"23\"");
|
|
||||||
tokenize.tokenize("\"1\\\"23\" abc123");
|
|
||||||
|
|
||||||
tokenize.tokenize("+0.012");
|
|
||||||
tokenize.tokenize("0.0");
|
|
||||||
tokenize.tokenize("-222.0");
|
|
||||||
tokenize.tokenize("1+1 ==2; 3+8 foo(12)");
|
|
||||||
|
|
||||||
console.log(tokenize.tokenize("2+2"));
|
|
||||||
|
|
||||||
// harfbuzz test
|
|
||||||
let harfbuzz = require("../src/harfbuzz.js");
|
|
||||||
harfbuzz.harfbuzzTest("123.abc");
|
|
||||||
|
|
||||||
// pdf test
|
|
||||||
let pdfManipulate = require("../src/pdfManipulate.js");
|
|
||||||
pdfManipulate.pdfGenerate("123.abc");
|
|
||||||
console.log("/tmp/test.pdf產出ah");
|
|
||||||
|
|
36
tests/pdfManipulation.ts
Normal file
36
tests/pdfManipulation.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import * as canva from "../src/canva.js";
|
||||||
|
import { PDFDocument } from "pdf-lib";
|
||||||
|
var fontkit = require('@pdf-lib/fontkit');
|
||||||
|
import {writeFileSync} from 'fs';
|
||||||
|
|
||||||
|
let hanziFont = {
|
||||||
|
name : "思源黑體",
|
||||||
|
size : 12,
|
||||||
|
textWeight : canva.TextWeight.BOLD,
|
||||||
|
textStyle : canva.TextStyle.ITALIC,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function foo (){
|
||||||
|
|
||||||
|
let c = await PDFDocument.create();
|
||||||
|
|
||||||
|
let clo = await {
|
||||||
|
mainText : ["123"],
|
||||||
|
mainFontStyle : hanziFont,
|
||||||
|
PDFCanvas : c,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
clo.PDFCanvas.registerFontkit(fontkit);
|
||||||
|
const page = clo.PDFCanvas.addPage();
|
||||||
|
|
||||||
|
await canva.putText(clo, clo.mainText[0],hanziFont, 0, 100, 200);
|
||||||
|
|
||||||
|
const pdfBytes = await clo.PDFCanvas.save();
|
||||||
|
|
||||||
|
writeFileSync('/tmp/test.pdf', pdfBytes);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
foo();
|
Loading…
Reference in a new issue