english breakline, and generate try to count the text size
This commit is contained in:
parent
796e0c20c7
commit
c3dc58d74a
80 changed files with 7617 additions and 1631 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -2,4 +2,5 @@ node_modules
|
|||
/src/*.js
|
||||
/tests/*.js
|
||||
.vscode
|
||||
activate.sh
|
||||
activate.sh
|
||||
docs/.nojekyll
|
||||
|
|
19
README.md
19
README.md
|
@ -1,7 +1,8 @@
|
|||
# clo
|
||||
another personal draught of a typesetting language and engine.
|
||||
website: https://kianting.info/wiki/w/Project:Clo
|
||||
License: MIT
|
||||
- another personal draught of a typesetting language and engine.
|
||||
- website: https://kianting.info/wiki/w/Project:Clo
|
||||
- license: MIT
|
||||
- issue tracking mailing list: `clo@kianting.info`
|
||||
|
||||
## changing journal
|
||||
- 20230904 建立 thenDo、matchRange的函數、refactor harfbuzzjs 以及libpdf 等測試界面
|
||||
|
@ -31,6 +32,7 @@ License: MIT
|
|||
- 20231023-24:fix .ttc bug.
|
||||
- 20231026-27 : clo basic interface, preprocessor of stream of text,
|
||||
add cjk-english splitter, etc.
|
||||
- 20231029: hyphenating for english.
|
||||
|
||||
## 之後的做法
|
||||
- 先做一個前處理註冊器,註冊下列的前處理
|
||||
|
@ -43,15 +45,20 @@ License: MIT
|
|||
- 然後算出每個Box的x, y, page
|
||||
- 最後納入排版
|
||||
|
||||
## 排版語法:
|
||||
## 排版語法
|
||||
|
||||
使用lisp表示,但其實是陣列
|
||||
```lisp
|
||||
(hglue 寬度 伸展值)
|
||||
(vglue 高度 伸展值)
|
||||
(breakpoint 原始模式 斷行模式)
|
||||
(bp 原始模式 斷行模式) ; breakpoint
|
||||
(nl) ; newline
|
||||
(em 數字)
|
||||
(ex 數字)
|
||||
(span {"font-family" : "Noto Sans" , "font-size" : 16 })
|
||||
(vbox 高度 內容)
|
||||
```
|
||||
```
|
||||
|
||||
## How to generate documents
|
||||
- `typedoc /path/to/index.js [/path/to/index2.js ...]`
|
||||
the generated page will be stored in `/src`.
|
12
b.clo
12
b.clo
|
@ -1,4 +1,12 @@
|
|||
---
|
||||
many臺中daylight
|
||||
The book of the generation of Jesus Christ, the son of David, the son of Abraham.
|
||||
|
||||
aaa collee
|
||||
Abraham begat Isaac; and Isaac begat Jacob; and Jacob begat Judas and his brethren; And Judas begat Phares and Zara of Thamar; and Phares begat Esrom; and Esrom begat Aram; And Aram begat Aminadab; and Aminadab begat Naasson; and Naasson begat Salmon; And Salmon begat Booz of Rachab; and Booz begat Obed of Ruth; and Obed begat Jesse; And Jesse begat David the king;
|
||||
|
||||
and David the king begat Solomon of her that had been the wife of Urias; And Solomon begat Roboam; and Roboam begat Abia; and Abia begat Asa; And Asa begat Josaphat; and Josaphat begat Joram; and Joram begat Ozias; And Ozias begat Joatham; and Joatham begat Achaz; and Achaz begat Ezekias; And Ezekias begat Manasses; and Manasses begat Amon; and Amon begat Josias; And Josias begat Jechonias and his brethren, about the time they were carried away to Babylon: And after they were brought to Babylon, Jechonias begat Salathiel; and Salathiel begat Zorobabel; And Zorobabel begat Abiud; and Abiud begat Eliakim; and Eliakim begat Azor; And Azor begat Sadoc; and Sadoc begat Achim; and Achim begat Eliud; And Eliud begat Eleazar; and Eleazar begat Matthan; and Matthan begat Jacob; And Jacob begat Joseph the husband of Mary, of whom was born Jesus, who is called Christ.
|
||||
|
||||
So all the generations from Abraham to David are fourteen generations; and from David until the carrying away into Babylon are fourteen generations; and from the carrying away into Babylon unto Christ are fourteen generations.
|
||||
|
||||
Now the birth of Jesus Christ was on this wise: When as his mother Mary was espoused to Joseph, before they came together, she was found with child of the Holy Ghost. Then Joseph her husband, being a just man, and not willing to make her a publick example, was minded to put her away privily. But while he thought on these things, behold, the angel of the Lord appeared unto him in a dream, saying, Joseph, thou son of David, fear not to take unto thee Mary thy wife: for that which is conceived in her is of the Holy Ghost. And she shall bring forth a son, and thou shalt call his name JESUS: for he shall save his people from their sins. Now all this was done, that it might be fulfilled which was spoken of the Lord by the prophet, saying, Behold, a virgin shall be with child, and shall bring forth a son, and they shall call his name Emmanuel, which being interpreted is, God with us.
|
||||
|
||||
Then Joseph being raised from sleep did as the angel of the Lord had bidden him, and took unto him his wife: And knew her not till she had brought forth her firstborn son: and he called his name JESUS. Now when Jesus was born in Bethlehem of Judaea in the days of Herod the king, behold, there came wise men from the east to Jerusalem, Saying, Where is he that is born King of the Jews?
|
13
b.js
13
b.js
|
@ -9,10 +9,17 @@ let clo = new cloLib.Clo();
|
|||
|
||||
/* CLO: beginning of middle part*/
|
||||
clo.mainStream = /* CLO: end of middle part*/
|
||||
[`
|
||||
`, `many臺中daylight`, `
|
||||
[`The`, ` `, `book`, ` `, `of`, ` `, `the`, ` `, `generation`, ` `, `of`, ` `, `Jesus`, ` `, `Christ,`, ` `, `the`, ` `, `son`, ` `, `of`, ` `, `David,`, ` `, `the`, ` `, `son`, ` `, `of`, ` `, `Abraham.`, `
|
||||
|
||||
`, `aaa`, ` `, `collee`];
|
||||
`, `Abraham`, ` `, `begat`, ` `, `Isaac`, `;`, ` `, `and`, ` `, `Isaac`, ` `, `begat`, ` `, `Jacob`, `;`, ` `, `and`, ` `, `Jacob`, ` `, `begat`, ` `, `Judas`, ` `, `and`, ` `, `his`, ` `, `brethren`, `;`, ` `, `And`, ` `, `Judas`, ` `, `begat`, ` `, `Phares`, ` `, `and`, ` `, `Zara`, ` `, `of`, ` `, `Thamar`, `;`, ` `, `and`, ` `, `Phares`, ` `, `begat`, ` `, `Esrom`, `;`, ` `, `and`, ` `, `Esrom`, ` `, `begat`, ` `, `Aram`, `;`, ` `, `And`, ` `, `Aram`, ` `, `begat`, ` `, `Aminadab`, `;`, ` `, `and`, ` `, `Aminadab`, ` `, `begat`, ` `, `Naasson`, `;`, ` `, `and`, ` `, `Naasson`, ` `, `begat`, ` `, `Salmon`, `;`, ` `, `And`, ` `, `Salmon`, ` `, `begat`, ` `, `Booz`, ` `, `of`, ` `, `Rachab`, `;`, ` `, `and`, ` `, `Booz`, ` `, `begat`, ` `, `Obed`, ` `, `of`, ` `, `Ruth`, `;`, ` `, `and`, ` `, `Obed`, ` `, `begat`, ` `, `Jesse`, `;`, ` `, `And`, ` `, `Jesse`, ` `, `begat`, ` `, `David`, ` `, `the`, ` `, `king`, `;`, `
|
||||
|
||||
`, `and`, ` `, `David`, ` `, `the`, ` `, `king`, ` `, `begat`, ` `, `Solomon`, ` `, `of`, ` `, `her`, ` `, `that`, ` `, `had`, ` `, `been`, ` `, `the`, ` `, `wife`, ` `, `of`, ` `, `Urias`, `;`, ` `, `And`, ` `, `Solomon`, ` `, `begat`, ` `, `Roboam`, `;`, ` `, `and`, ` `, `Roboam`, ` `, `begat`, ` `, `Abia`, `;`, ` `, `and`, ` `, `Abia`, ` `, `begat`, ` `, `Asa`, `;`, ` `, `And`, ` `, `Asa`, ` `, `begat`, ` `, `Josaphat`, `;`, ` `, `and`, ` `, `Josaphat`, ` `, `begat`, ` `, `Joram`, `;`, ` `, `and`, ` `, `Joram`, ` `, `begat`, ` `, `Ozias`, `;`, ` `, `And`, ` `, `Ozias`, ` `, `begat`, ` `, `Joatham`, `;`, ` `, `and`, ` `, `Joatham`, ` `, `begat`, ` `, `Achaz`, `;`, ` `, `and`, ` `, `Achaz`, ` `, `begat`, ` `, `Ezekias`, `;`, ` `, `And`, ` `, `Ezekias`, ` `, `begat`, ` `, `Manasses`, `;`, ` `, `and`, ` `, `Manasses`, ` `, `begat`, ` `, `Amon`, `;`, ` `, `and`, ` `, `Amon`, ` `, `begat`, ` `, `Josias`, `;`, ` `, `And`, ` `, `Josias`, ` `, `begat`, ` `, `Jechonias`, ` `, `and`, ` `, `his`, ` `, `brethren,`, ` `, `about`, ` `, `the`, ` `, `time`, ` `, `they`, ` `, `were`, ` `, `carried`, ` `, `away`, ` `, `to`, ` `, `Babylon:`, ` `, `And`, ` `, `after`, ` `, `they`, ` `, `were`, ` `, `brought`, ` `, `to`, ` `, `Babylon,`, ` `, `Jechonias`, ` `, `begat`, ` `, `Salathiel`, `;`, ` `, `and`, ` `, `Salathiel`, ` `, `begat`, ` `, `Zorobabel`, `;`, ` `, `And`, ` `, `Zorobabel`, ` `, `begat`, ` `, `Abiud`, `;`, ` `, `and`, ` `, `Abiud`, ` `, `begat`, ` `, `Eliakim`, `;`, ` `, `and`, ` `, `Eliakim`, ` `, `begat`, ` `, `Azor`, `;`, ` `, `And`, ` `, `Azor`, ` `, `begat`, ` `, `Sadoc`, `;`, ` `, `and`, ` `, `Sadoc`, ` `, `begat`, ` `, `Achim`, `;`, ` `, `and`, ` `, `Achim`, ` `, `begat`, ` `, `Eliud`, `;`, ` `, `And`, ` `, `Eliud`, ` `, `begat`, ` `, `Eleazar`, `;`, ` `, `and`, ` `, `Eleazar`, ` `, `begat`, ` `, `Matthan`, `;`, ` `, `and`, ` `, `Matthan`, ` `, `begat`, ` `, `Jacob`, `;`, ` `, `And`, ` `, `Jacob`, ` `, `begat`, ` `, `Joseph`, ` `, `the`, ` `, `husband`, ` `, `of`, ` `, `Mary,`, ` `, `of`, ` `, `whom`, ` `, `was`, ` `, `born`, ` `, `Jesus,`, ` `, `who`, ` `, `is`, ` `, `called`, ` `, `Christ.`, `
|
||||
|
||||
`, `So`, ` `, `all`, ` `, `the`, ` `, `generations`, ` `, `from`, ` `, `Abraham`, ` `, `to`, ` `, `David`, ` `, `are`, ` `, `fourteen`, ` `, `generations`, `;`, ` `, `and`, ` `, `from`, ` `, `David`, ` `, `until`, ` `, `the`, ` `, `carrying`, ` `, `away`, ` `, `into`, ` `, `Babylon`, ` `, `are`, ` `, `fourteen`, ` `, `generations`, `;`, ` `, `and`, ` `, `from`, ` `, `the`, ` `, `carrying`, ` `, `away`, ` `, `into`, ` `, `Babylon`, ` `, `unto`, ` `, `Christ`, ` `, `are`, ` `, `fourteen`, ` `, `generations.`, `
|
||||
|
||||
`, `Now`, ` `, `the`, ` `, `birth`, ` `, `of`, ` `, `Jesus`, ` `, `Christ`, ` `, `was`, ` `, `on`, ` `, `this`, ` `, `wise:`, ` `, `When`, ` `, `as`, ` `, `his`, ` `, `mother`, ` `, `Mary`, ` `, `was`, ` `, `espoused`, ` `, `to`, ` `, `Joseph,`, ` `, `before`, ` `, `they`, ` `, `came`, ` `, `together,`, ` `, `she`, ` `, `was`, ` `, `found`, ` `, `with`, ` `, `child`, ` `, `of`, ` `, `the`, ` `, `Holy`, ` `, `Ghost.`, ` `, `Then`, ` `, `Joseph`, ` `, `her`, ` `, `husband,`, ` `, `being`, ` `, `a`, ` `, `just`, ` `, `man,`, ` `, `and`, ` `, `not`, ` `, `willing`, ` `, `to`, ` `, `make`, ` `, `her`, ` `, `a`, ` `, `publick`, ` `, `example,`, ` `, `was`, ` `, `minded`, ` `, `to`, ` `, `put`, ` `, `her`, ` `, `away`, ` `, `privily.`, ` `, `But`, ` `, `while`, ` `, `he`, ` `, `thought`, ` `, `on`, ` `, `these`, ` `, `things,`, ` `, `behold,`, ` `, `the`, ` `, `angel`, ` `, `of`, ` `, `the`, ` `, `Lord`, ` `, `appeared`, ` `, `unto`, ` `, `him`, ` `, `in`, ` `, `a`, ` `, `dream,`, ` `, `saying,`, ` `, `Joseph,`, ` `, `thou`, ` `, `son`, ` `, `of`, ` `, `David,`, ` `, `fear`, ` `, `not`, ` `, `to`, ` `, `take`, ` `, `unto`, ` `, `thee`, ` `, `Mary`, ` `, `thy`, ` `, `wife:`, ` `, `for`, ` `, `that`, ` `, `which`, ` `, `is`, ` `, `conceived`, ` `, `in`, ` `, `her`, ` `, `is`, ` `, `of`, ` `, `the`, ` `, `Holy`, ` `, `Ghost.`, ` `, `And`, ` `, `she`, ` `, `shall`, ` `, `bring`, ` `, `forth`, ` `, `a`, ` `, `son,`, ` `, `and`, ` `, `thou`, ` `, `shalt`, ` `, `call`, ` `, `his`, ` `, `name`, ` `, `JESUS:`, ` `, `for`, ` `, `he`, ` `, `shall`, ` `, `save`, ` `, `his`, ` `, `people`, ` `, `from`, ` `, `their`, ` `, `sins.`, ` `, `Now`, ` `, `all`, ` `, `this`, ` `, `was`, ` `, `done,`, ` `, `that`, ` `, `it`, ` `, `might`, ` `, `be`, ` `, `fulfilled`, ` `, `which`, ` `, `was`, ` `, `spoken`, ` `, `of`, ` `, `the`, ` `, `Lord`, ` `, `by`, ` `, `the`, ` `, `prophet,`, ` `, `saying,`, ` `, `Behold,`, ` `, `a`, ` `, `virgin`, ` `, `shall`, ` `, `be`, ` `, `with`, ` `, `child,`, ` `, `and`, ` `, `shall`, ` `, `bring`, ` `, `forth`, ` `, `a`, ` `, `son,`, ` `, `and`, ` `, `they`, ` `, `shall`, ` `, `call`, ` `, `his`, ` `, `name`, ` `, `Emmanuel,`, ` `, `which`, ` `, `being`, ` `, `interpreted`, ` `, `is,`, ` `, `God`, ` `, `with`, ` `, `us.`, `
|
||||
|
||||
`, `Then`, ` `, `Joseph`, ` `, `being`, ` `, `raised`, ` `, `from`, ` `, `sleep`, ` `, `did`, ` `, `as`, ` `, `the`, ` `, `angel`, ` `, `of`, ` `, `the`, ` `, `Lord`, ` `, `had`, ` `, `bidden`, ` `, `him,`, ` `, `and`, ` `, `took`, ` `, `unto`, ` `, `him`, ` `, `his`, ` `, `wife:`, ` `, `And`, ` `, `knew`, ` `, `her`, ` `, `not`, ` `, `till`, ` `, `she`, ` `, `had`, ` `, `brought`, ` `, `forth`, ` `, `her`, ` `, `firstborn`, ` `, `son:`, ` `, `and`, ` `, `he`, ` `, `called`, ` `, `his`, ` `, `name`, ` `, `JESUS.`, ` `, `Now`, ` `, `when`, ` `, `Jesus`, ` `, `was`, ` `, `born`, ` `, `in`, ` `, `Bethlehem`, ` `, `of`, ` `, `Judaea`, ` `, `in`, ` `, `the`, ` `, `days`, ` `, `of`, ` `, `Herod`, ` `, `the`, ` `, `king,`, ` `, `behold,`, ` `, `there`, ` `, `came`, ` `, `wise`, ` `, `men`, ` `, `from`, ` `, `the`, ` `, `east`, ` `, `to`, ` `, `Jerusalem,`, ` `, `Saying,`, ` `, `Where`, ` `, `is`, ` `, `he`, ` `, `that`, ` `, `is`, ` `, `born`, ` `, `King`, ` `, `of`, ` `, `the`, ` `, `Jews?`, ` `];
|
||||
/* CLO: beginning of end part*/
|
||||
clo.generatePdf();
|
||||
/*CLO : end of end part*/
|
||||
|
|
78
docs/assets/highlight.css
Normal file
78
docs/assets/highlight.css
Normal file
|
@ -0,0 +1,78 @@
|
|||
:root {
|
||||
--light-hl-0: #000000;
|
||||
--dark-hl-0: #C8C8C8;
|
||||
--light-hl-1: #000000;
|
||||
--dark-hl-1: #D4D4D4;
|
||||
--light-hl-2: #001080;
|
||||
--dark-hl-2: #9CDCFE;
|
||||
--light-hl-3: #A31515;
|
||||
--dark-hl-3: #CE9178;
|
||||
--light-hl-4: #0070C1;
|
||||
--dark-hl-4: #4FC1FF;
|
||||
--light-hl-5: #008000;
|
||||
--dark-hl-5: #6A9955;
|
||||
--light-hl-6: #0000FF;
|
||||
--dark-hl-6: #569CD6;
|
||||
--light-hl-7: #098658;
|
||||
--dark-hl-7: #B5CEA8;
|
||||
--light-code-background: #FFFFFF;
|
||||
--dark-code-background: #1E1E1E;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) { :root {
|
||||
--hl-0: var(--light-hl-0);
|
||||
--hl-1: var(--light-hl-1);
|
||||
--hl-2: var(--light-hl-2);
|
||||
--hl-3: var(--light-hl-3);
|
||||
--hl-4: var(--light-hl-4);
|
||||
--hl-5: var(--light-hl-5);
|
||||
--hl-6: var(--light-hl-6);
|
||||
--hl-7: var(--light-hl-7);
|
||||
--code-background: var(--light-code-background);
|
||||
} }
|
||||
|
||||
@media (prefers-color-scheme: dark) { :root {
|
||||
--hl-0: var(--dark-hl-0);
|
||||
--hl-1: var(--dark-hl-1);
|
||||
--hl-2: var(--dark-hl-2);
|
||||
--hl-3: var(--dark-hl-3);
|
||||
--hl-4: var(--dark-hl-4);
|
||||
--hl-5: var(--dark-hl-5);
|
||||
--hl-6: var(--dark-hl-6);
|
||||
--hl-7: var(--dark-hl-7);
|
||||
--code-background: var(--dark-code-background);
|
||||
} }
|
||||
|
||||
:root[data-theme='light'] {
|
||||
--hl-0: var(--light-hl-0);
|
||||
--hl-1: var(--light-hl-1);
|
||||
--hl-2: var(--light-hl-2);
|
||||
--hl-3: var(--light-hl-3);
|
||||
--hl-4: var(--light-hl-4);
|
||||
--hl-5: var(--light-hl-5);
|
||||
--hl-6: var(--light-hl-6);
|
||||
--hl-7: var(--light-hl-7);
|
||||
--code-background: var(--light-code-background);
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] {
|
||||
--hl-0: var(--dark-hl-0);
|
||||
--hl-1: var(--dark-hl-1);
|
||||
--hl-2: var(--dark-hl-2);
|
||||
--hl-3: var(--dark-hl-3);
|
||||
--hl-4: var(--dark-hl-4);
|
||||
--hl-5: var(--dark-hl-5);
|
||||
--hl-6: var(--dark-hl-6);
|
||||
--hl-7: var(--dark-hl-7);
|
||||
--code-background: var(--dark-code-background);
|
||||
}
|
||||
|
||||
.hl-0 { color: var(--hl-0); }
|
||||
.hl-1 { color: var(--hl-1); }
|
||||
.hl-2 { color: var(--hl-2); }
|
||||
.hl-3 { color: var(--hl-3); }
|
||||
.hl-4 { color: var(--hl-4); }
|
||||
.hl-5 { color: var(--hl-5); }
|
||||
.hl-6 { color: var(--hl-6); }
|
||||
.hl-7 { color: var(--hl-7); }
|
||||
pre, code { background: var(--code-background); }
|
59
docs/assets/main.js
Normal file
59
docs/assets/main.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/assets/navigation.js
Normal file
1
docs/assets/navigation.js
Normal file
|
@ -0,0 +1 @@
|
|||
window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA42XW0/bMBSA/0ue0TYYsI230gZWoGnUZAMJocqkbuPVsaPEKa2m/fe5iZM6t+M8leZ8/hpfzvHh9a8l8F5YN1aA2A5ZZ1aMRCi/RnyVUZx+zh9/CkVEZWxL2Mq6uTizgpDQVYKZdfNaCXz54YkDxScJZllUKqpwXfb931nN8IzJJhT9iiLe7xhTfhpMmMDJGgXVPGS0MZer6/rgMY8iJCOgQ0GQ6o6z5mq0TBUDidYScqXA9RwUYReRBDC2YUjtTu4mPMgizLQFF4e40mlAw/Plx7fzq4vG3nkiwSj6xUiPrs6YjOtydXx+/POkXGcsEIQzfdIaWPdeX2rKOBPHd+hXKaCleNMk8hnetxMlfzwoUUJM4wlOg5NjhxKC3jWLIuq6r/rqxAmX256Oks2uazqFR4PAKVHyHuh5U86peD5oUhOS4Py3m6mrHFV8YOoGFKXp6RVaiXt+oQ+95fvOrFCjZRjM1UQmi0FRMpBndLmcOkv3pWtjlaZEgJ0N/mx3t5QH23TKFnijn7WWrsUavDkjC4ScHTNodRSwrvAaZVTky9Oody1tizV7Oy6VPm3PBVOzhoc4xOyOJ7Wzdkqb8sBrGFBOCszf+gnGRluBQcVJ+NzdA54CAAxpTIkYPzz+BiQVA3jEB19gkSUs9bmDPyhh0PQ6aLDYxChJcdIuNsXzYa0G32L2SPRruig2ylHF+4uNaOxacU+p8aJjr9oX1Hju+Lbjd51M5VEEcCCnM3e+gBQFYDTYttFh20aLZ5R4gMOZ+8sRNJcCMBqWvv1i1uQU4HIX83tAcgwDoz37fgbvrSJAx2w6nj/NHdCiGMBD8V7Pl5YjjwPjeSZkX2Pr2dJyVIzR8xMjs+gIGU0zslp1F/aaq8AAG4pjeji25Li7S1Q2HQOKn8JkAzDElmMm2zSKeWKUFdQwVzpMlppsDhej3pZY91WgyeiiAW+XQ4NMz0SE8hgMW8H2CNNveHgz5NQozGyLyJhTvQfu8ynQaIxlD+o8GX0FZrIN2WjDHhOm/kXyeV/Xo2wNEmo3ZNjnDx4gK5GOxuLtPxjWUt7DEAAA"
|
1
docs/assets/search.js
Normal file
1
docs/assets/search.js
Normal file
File diff suppressed because one or more lines are too long
1383
docs/assets/style.css
Normal file
1383
docs/assets/style.css
Normal file
File diff suppressed because it is too large
Load diff
185
docs/classes/libclo.Clo.html
Normal file
185
docs/classes/libclo.Clo.html
Normal file
File diff suppressed because one or more lines are too long
80
docs/enums/canva.TextStyle.html
Normal file
80
docs/enums/canva.TextStyle.html
Normal file
File diff suppressed because one or more lines are too long
73
docs/enums/canva.TextWeight.html
Normal file
73
docs/enums/canva.TextWeight.html
Normal file
File diff suppressed because one or more lines are too long
94
docs/enums/libclo.Direction.html
Normal file
94
docs/enums/libclo.Direction.html
Normal file
File diff suppressed because one or more lines are too long
136
docs/enums/parser.TokenKind.html
Normal file
136
docs/enums/parser.TokenKind.html
Normal file
File diff suppressed because one or more lines are too long
62
docs/functions/canva.fontStyleTofont.html
Normal file
62
docs/functions/canva.fontStyleTofont.html
Normal file
File diff suppressed because one or more lines are too long
84
docs/functions/canva.putText.html
Normal file
84
docs/functions/canva.putText.html
Normal file
File diff suppressed because one or more lines are too long
60
docs/functions/index.processArgv.html
Normal file
60
docs/functions/index.processArgv.html
Normal file
File diff suppressed because one or more lines are too long
66
docs/functions/libclo.hyphenForClo.html
Normal file
66
docs/functions/libclo.hyphenForClo.html
Normal file
File diff suppressed because one or more lines are too long
66
docs/functions/libclo.hyphenTkTree.html
Normal file
66
docs/functions/libclo.hyphenTkTree.html
Normal file
File diff suppressed because one or more lines are too long
62
docs/functions/libclo.ptToPx.html
Normal file
62
docs/functions/libclo.ptToPx.html
Normal file
File diff suppressed because one or more lines are too long
69
docs/functions/libclo.splitCJKV.html
Normal file
69
docs/functions/libclo.splitCJKV.html
Normal file
File diff suppressed because one or more lines are too long
60
docs/functions/libclo.twoReturnsToNewline.html
Normal file
60
docs/functions/libclo.twoReturnsToNewline.html
Normal file
File diff suppressed because one or more lines are too long
55
docs/functions/parser.applyComment.html
Normal file
55
docs/functions/parser.applyComment.html
Normal file
File diff suppressed because one or more lines are too long
55
docs/functions/parser.applyContent.html
Normal file
55
docs/functions/parser.applyContent.html
Normal file
File diff suppressed because one or more lines are too long
55
docs/functions/parser.applyImport.html
Normal file
55
docs/functions/parser.applyImport.html
Normal file
File diff suppressed because one or more lines are too long
55
docs/functions/parser.applyImports.html
Normal file
55
docs/functions/parser.applyImports.html
Normal file
File diff suppressed because one or more lines are too long
55
docs/functions/parser.applyNotAtText.html
Normal file
55
docs/functions/parser.applyNotAtText.html
Normal file
File diff suppressed because one or more lines are too long
57
docs/functions/parser.applyParts.html
Normal file
57
docs/functions/parser.applyParts.html
Normal file
File diff suppressed because one or more lines are too long
55
docs/functions/parser.applyPartsWithoutImport.html
Normal file
55
docs/functions/parser.applyPartsWithoutImport.html
Normal file
File diff suppressed because one or more lines are too long
55
docs/functions/parser.applySegment.html
Normal file
55
docs/functions/parser.applySegment.html
Normal file
File diff suppressed because one or more lines are too long
55
docs/functions/parser.applySemiColon.html
Normal file
55
docs/functions/parser.applySemiColon.html
Normal file
File diff suppressed because one or more lines are too long
55
docs/functions/parser.applySpaceNL.html
Normal file
55
docs/functions/parser.applySpaceNL.html
Normal file
File diff suppressed because one or more lines are too long
55
docs/functions/parser.applyText.html
Normal file
55
docs/functions/parser.applyText.html
Normal file
File diff suppressed because one or more lines are too long
58
docs/functions/parser.inputTextToTree.html
Normal file
58
docs/functions/parser.inputTextToTree.html
Normal file
File diff suppressed because one or more lines are too long
58
docs/functions/parser.treeToJS.html
Normal file
58
docs/functions/parser.treeToJS.html
Normal file
File diff suppressed because one or more lines are too long
109
docs/index.html
Normal file
109
docs/index.html
Normal file
File diff suppressed because one or more lines are too long
88
docs/interfaces/canva.Clo.html
Normal file
88
docs/interfaces/canva.Clo.html
Normal file
File diff suppressed because one or more lines are too long
77
docs/interfaces/canva.CloCommand.html
Normal file
77
docs/interfaces/canva.CloCommand.html
Normal file
File diff suppressed because one or more lines are too long
106
docs/interfaces/canva.FontStyle.html
Normal file
106
docs/interfaces/canva.FontStyle.html
Normal file
File diff suppressed because one or more lines are too long
77
docs/interfaces/canva.fontPathPSNamePair.html
Normal file
77
docs/interfaces/canva.fontPathPSNamePair.html
Normal file
File diff suppressed because one or more lines are too long
118
docs/interfaces/libclo.Box.html
Normal file
118
docs/interfaces/libclo.Box.html
Normal file
File diff suppressed because one or more lines are too long
143
docs/interfaces/libclo.FrameBox.html
Normal file
143
docs/interfaces/libclo.FrameBox.html
Normal file
File diff suppressed because one or more lines are too long
69
docs/modules/canva.html
Normal file
69
docs/modules/canva.html
Normal file
File diff suppressed because one or more lines are too long
55
docs/modules/index.html
Normal file
55
docs/modules/index.html
Normal file
File diff suppressed because one or more lines are too long
76
docs/modules/libclo.html
Normal file
76
docs/modules/libclo.html
Normal file
File diff suppressed because one or more lines are too long
87
docs/modules/parser.html
Normal file
87
docs/modules/parser.html
Normal file
File diff suppressed because one or more lines are too long
46
docs/types/canva.PDFDocument.html
Normal file
46
docs/types/canva.PDFDocument.html
Normal file
File diff suppressed because one or more lines are too long
46
docs/types/canva.TextStreamUnit.html
Normal file
46
docs/types/canva.TextStreamUnit.html
Normal file
File diff suppressed because one or more lines are too long
67
docs/types/parser.tkTree.html
Normal file
67
docs/types/parser.tkTree.html
Normal file
File diff suppressed because one or more lines are too long
49
docs/variables/index.helpDesc.html
Normal file
49
docs/variables/index.helpDesc.html
Normal file
File diff suppressed because one or more lines are too long
56
docs/variables/libclo.A4_IN_PX.html
Normal file
56
docs/variables/libclo.A4_IN_PX.html
Normal file
File diff suppressed because one or more lines are too long
56
docs/variables/libclo.cjkvBlocksInRegex.html
Normal file
56
docs/variables/libclo.cjkvBlocksInRegex.html
Normal file
File diff suppressed because one or more lines are too long
46
docs/variables/libclo.cjkvRegexPattern.html
Normal file
46
docs/variables/libclo.cjkvRegexPattern.html
Normal file
File diff suppressed because one or more lines are too long
46
docs/variables/libclo.defaultFrameStyle.html
Normal file
46
docs/variables/libclo.defaultFrameStyle.html
Normal file
File diff suppressed because one or more lines are too long
46
docs/variables/libclo.defaultTextStyle.html
Normal file
46
docs/variables/libclo.defaultTextStyle.html
Normal file
File diff suppressed because one or more lines are too long
46
docs/variables/parser.CONTENT.html
Normal file
46
docs/variables/parser.CONTENT.html
Normal file
File diff suppressed because one or more lines are too long
46
docs/variables/parser.IMPORT.html
Normal file
46
docs/variables/parser.IMPORT.html
Normal file
File diff suppressed because one or more lines are too long
49
docs/variables/parser.IMPORTEE.html
Normal file
49
docs/variables/parser.IMPORTEE.html
Normal file
File diff suppressed because one or more lines are too long
46
docs/variables/parser.IMPORTS.html
Normal file
46
docs/variables/parser.IMPORTS.html
Normal file
File diff suppressed because one or more lines are too long
46
docs/variables/parser.NOT_AT.html
Normal file
46
docs/variables/parser.NOT_AT.html
Normal file
File diff suppressed because one or more lines are too long
46
docs/variables/parser.NOT_AT_TEXT.html
Normal file
46
docs/variables/parser.NOT_AT_TEXT.html
Normal file
File diff suppressed because one or more lines are too long
55
docs/variables/parser.PROG.html
Normal file
55
docs/variables/parser.PROG.html
Normal file
File diff suppressed because one or more lines are too long
46
docs/variables/parser.SEGMENT.html
Normal file
46
docs/variables/parser.SEGMENT.html
Normal file
File diff suppressed because one or more lines are too long
46
docs/variables/parser.SEMICOLON.html
Normal file
46
docs/variables/parser.SEMICOLON.html
Normal file
File diff suppressed because one or more lines are too long
49
docs/variables/parser.lexer.html
Normal file
49
docs/variables/parser.lexer.html
Normal file
File diff suppressed because one or more lines are too long
49
docs/variables/parser.outputEnd.html
Normal file
49
docs/variables/parser.outputEnd.html
Normal file
File diff suppressed because one or more lines are too long
49
docs/variables/parser.outputHead.html
Normal file
49
docs/variables/parser.outputHead.html
Normal file
File diff suppressed because one or more lines are too long
49
docs/variables/parser.outputMiddle.html
Normal file
49
docs/variables/parser.outputMiddle.html
Normal file
File diff suppressed because one or more lines are too long
3043
package-lock.json
generated
3043
package-lock.json
generated
File diff suppressed because it is too large
Load diff
12
package.json
12
package.json
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Yoxem/clo.git"
|
||||
"url": "git+https://git.kianting.info/src/clo"
|
||||
},
|
||||
"keywords": [
|
||||
"typesetting"
|
||||
|
@ -17,11 +17,12 @@
|
|||
"author": "Tan Kian-ting",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Yoxem/clo/issues"
|
||||
"url": "https://kianting.info/wiki/w/Project:Clo#Discussion"
|
||||
},
|
||||
"homepage": "https://github.com/Yoxem/clo#readme",
|
||||
"homepage": "https://kianting.info/wiki/w/Project:Clo",
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.3.5",
|
||||
"@types/jsdom": "^21.1.4",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/node": "^20.8.4",
|
||||
"@types/pdfkit": "^0.13.1",
|
||||
|
@ -36,10 +37,13 @@
|
|||
"nyc": "^15.1.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"tslint": "^6.1.3",
|
||||
"typedoc": "^0.25.2",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"harfbuzzjs": "^0.3.3",
|
||||
"canvas": "^2.11.2",
|
||||
"hyphen": "^1.7.0",
|
||||
"jsdom": "^22.1.0",
|
||||
"minimist": "^1.2.8",
|
||||
"npx": "^10.2.2",
|
||||
"pdfkit": "^0.13.0",
|
||||
|
|
20
src/canva.ts
20
src/canva.ts
|
@ -23,16 +23,16 @@ export interface Clo{
|
|||
|
||||
/**
|
||||
* Font Style Interface
|
||||
* family : eg. "FreeSans"
|
||||
* size : in px, not in pt.
|
||||
* textWeight : TextWeight.REGULAR ,etc
|
||||
* textWeight : TextStyle.ITALIC ,etc
|
||||
* - family : eg. "FreeSans"
|
||||
* - size : in px, not in pt.
|
||||
* - textWeight : TextWeight.REGULAR ,etc
|
||||
* - fontStyle : FontStyle.ITALIC ,etc
|
||||
*/
|
||||
export interface FontStyle{
|
||||
export interface TextStyle{
|
||||
family : string,
|
||||
size : number,
|
||||
textWeight : TextWeight,
|
||||
textStyle : TextStyle,
|
||||
fontStyle : FontStyle,
|
||||
color? : string,
|
||||
};
|
||||
|
||||
|
@ -41,7 +41,7 @@ export enum TextWeight {
|
|||
BOLD,
|
||||
};
|
||||
|
||||
export enum TextStyle{
|
||||
export enum FontStyle{
|
||||
NORMAL,
|
||||
ITALIC,
|
||||
OBLIQUE,
|
||||
|
@ -57,10 +57,10 @@ export interface fontPathPSNamePair{
|
|||
* @param style the font style
|
||||
* @returns pair of the font path and postscript name.
|
||||
*/
|
||||
export function fontStyleTofont(style : FontStyle) : fontPathPSNamePair{
|
||||
export function fontStyleTofont(style : TextStyle) : fontPathPSNamePair{
|
||||
try {
|
||||
let fcMatchCommand = `fc-match "${style.family}":${TextWeight[style.textWeight]}:`+
|
||||
`${TextStyle[style.textStyle]}` +` postscriptname file`;
|
||||
`${FontStyle[style.fontStyle]}` +` postscriptname file`;
|
||||
|
||||
let fcMatchOut = execSync(fcMatchCommand);
|
||||
let matched = fcMatchOut
|
||||
|
@ -93,7 +93,7 @@ export function fontStyleTofont(style : FontStyle) : fontPathPSNamePair{
|
|||
* @param y base y-point from top
|
||||
* @returns a new updated clo object
|
||||
*/
|
||||
export async function putText(clo : Clo, str : string, sty : FontStyle,
|
||||
export async function putText(clo : Clo, str : string, sty : TextStyle,
|
||||
pageNo : number, x : number, y : number): Promise<Clo>{
|
||||
|
||||
let fontInfo = fontStyleTofont(sty);
|
||||
|
|
|
@ -23,10 +23,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.processArgv = exports.helpDesc = void 0;
|
||||
var fs = require('fs');
|
||||
var argv = require('minimist')(process.argv.slice(2));
|
||||
const parser = __importStar(require("./parser.js"));
|
||||
let helpDesc = `
|
||||
/**
|
||||
* help for inputing `--help` parameter.
|
||||
*/
|
||||
exports.helpDesc = `
|
||||
clo: clo INPUT_FILE --output-js OUTPUT_JS_FILE
|
||||
|
||||
\ta little typesetter powered by TypeScript/Javascript.
|
||||
|
@ -42,7 +46,7 @@ INPUT_FILE\tan input .clo file
|
|||
Report bugs to: clo@kianting.info
|
||||
clo home page: <https://kianting.info/wiki/w/Project:Clo>
|
||||
`;
|
||||
processArgv(argv, helpDesc);
|
||||
processArgv(argv, exports.helpDesc);
|
||||
/**
|
||||
* processing the passed `argv` (arguments)
|
||||
*/
|
||||
|
@ -72,3 +76,4 @@ function processArgv(argv, helpDesc) {
|
|||
});
|
||||
}
|
||||
}
|
||||
exports.processArgv = processArgv;
|
||||
|
|
|
@ -3,8 +3,10 @@ var argv : any = require('minimist')(process.argv.slice(2));
|
|||
|
||||
import * as parser from "./parser.js";
|
||||
|
||||
|
||||
let helpDesc =
|
||||
/**
|
||||
* help for inputing `--help` parameter.
|
||||
*/
|
||||
export let helpDesc =
|
||||
`
|
||||
clo: clo INPUT_FILE --output-js OUTPUT_JS_FILE
|
||||
|
||||
|
@ -28,7 +30,7 @@ processArgv(argv, helpDesc);
|
|||
* processing the passed `argv` (arguments)
|
||||
*/
|
||||
|
||||
function processArgv(argv : any, helpDesc : string){
|
||||
export function processArgv(argv : any, helpDesc : string){
|
||||
let inputFile : string[] = argv['_'];
|
||||
let outputJSFile : string | true = argv['output-js'];
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.a = exports.Clo = void 0;
|
||||
exports.Clo = exports.calculateTextWidthHeight = exports.hyphenTkTree = exports.filterEmptyString = exports.spacesToBreakpoint = exports.hyphenForClo = exports.splitCJKV = exports.twoReturnsToNewline = exports.ptToPx = exports.cjkvRegexPattern = exports.cjkvBlocksInRegex = exports.defaultFrameStyle = exports.defaultTextStyle = exports.A4_IN_PX = exports.Direction = void 0;
|
||||
const canva_1 = require("../canva");
|
||||
const jsdom_1 = require("jsdom");
|
||||
/**
|
||||
* TYPES
|
||||
*/
|
||||
|
@ -17,32 +18,40 @@ var Direction;
|
|||
Direction[Direction["RTL"] = 1] = "RTL";
|
||||
Direction[Direction["TTB"] = 2] = "TTB";
|
||||
Direction[Direction["BTT"] = 3] = "BTT";
|
||||
})(Direction || (Direction = {}));
|
||||
})(Direction || (exports.Direction = Direction = {}));
|
||||
/**
|
||||
* DEFAULT CONST PART
|
||||
*/
|
||||
const A4_IN_PX = { "width": 793.7,
|
||||
exports.A4_IN_PX = { "width": 793.7,
|
||||
"height": 1122.5 };
|
||||
const defaultTextStyle = {
|
||||
family: "FreeSans",
|
||||
size: 12,
|
||||
exports.defaultTextStyle = {
|
||||
family: "FreeSerif",
|
||||
size: ptToPx(12),
|
||||
textWeight: canva_1.TextWeight.REGULAR,
|
||||
textStyle: canva_1.TextStyle.ITALIC,
|
||||
fontStyle: canva_1.FontStyle.ITALIC,
|
||||
};
|
||||
const defaultFrameStyle = {
|
||||
exports.defaultFrameStyle = {
|
||||
directionInsideLine: Direction.LTR,
|
||||
direction: Direction.TTB,
|
||||
baseLineskip: ptToPx(15),
|
||||
fontStyle: defaultTextStyle,
|
||||
x: A4_IN_PX.width * 0.10,
|
||||
y: A4_IN_PX.height * 0.10,
|
||||
width: A4_IN_PX.width * 0.80,
|
||||
height: A4_IN_PX.height * 0.80,
|
||||
textStyle: exports.defaultTextStyle,
|
||||
x: exports.A4_IN_PX.width * 0.10,
|
||||
y: exports.A4_IN_PX.height * 0.10,
|
||||
width: exports.A4_IN_PX.width * 0.80,
|
||||
height: exports.A4_IN_PX.height * 0.80,
|
||||
content: null,
|
||||
};
|
||||
const cjkvBlocksInRegex = ["Hani"];
|
||||
const cjkvRegexPattern = new RegExp("((?:" +
|
||||
cjkvBlocksInRegex.map((x) => "\\p{Script_Extensions=" + x + "}").join("|") + ")+)", "gu");
|
||||
/**
|
||||
* definition for cjk scripts
|
||||
* - Hani : Han Character
|
||||
* - Hang : Hangul
|
||||
* - Bopo : Bopomofo
|
||||
* - Kana : Katakana
|
||||
* - Hira : Hiragana
|
||||
*/
|
||||
exports.cjkvBlocksInRegex = ["Hani", "Hang", "Bopo", "Kana", "Hira"];
|
||||
exports.cjkvRegexPattern = new RegExp("((?:" +
|
||||
exports.cjkvBlocksInRegex.map((x) => "\\p{Script_Extensions=" + x + "}").join("|") + ")+)", "gu");
|
||||
/**
|
||||
* FUNCTION PART
|
||||
*/
|
||||
|
@ -52,47 +61,208 @@ const cjkvRegexPattern = new RegExp("((?:" +
|
|||
* @returns the corresponding px value
|
||||
*/
|
||||
function ptToPx(pt) {
|
||||
return pt * 4 / 3.0;
|
||||
return pt * 4.0 / 3.0;
|
||||
}
|
||||
exports.ptToPx = ptToPx;
|
||||
/**
|
||||
* REGISTER PART
|
||||
*/
|
||||
/**
|
||||
* convert '\n\n' to newline command ["nl"]
|
||||
* @param arr the input `tkTree`
|
||||
* @param clo the `Clo` object
|
||||
* @returns the input tktree
|
||||
*/
|
||||
function twoReturnsToNewline(arr, clo) {
|
||||
var middle = [];
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
var item = arr[i];
|
||||
if (!Array.isArray(item)) {
|
||||
middle = middle.concat(item.split(/(\n\n)/g));
|
||||
}
|
||||
else {
|
||||
middle.push(item);
|
||||
}
|
||||
}
|
||||
var result = [];
|
||||
for (let j = 0; j < middle.length; j++) {
|
||||
var item = middle[j];
|
||||
if (!Array.isArray(item) && item == "\n\n") {
|
||||
result.push(["nl"]); // push a newline command to the result `tkTree`
|
||||
}
|
||||
else {
|
||||
result.push(middle[j]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
exports.twoReturnsToNewline = twoReturnsToNewline;
|
||||
/**
|
||||
* split CJKV and non-CJKV
|
||||
*
|
||||
* @param arr : input tkTree
|
||||
* @returns
|
||||
* @returns a splitted tkTree (by CJK and NonCJK)
|
||||
* - Examples:
|
||||
* ```
|
||||
* [`many臺中daylight`] => [`many`, `臺中`, `dahylight`]
|
||||
* ```
|
||||
*/
|
||||
function splitCJKV(arr) {
|
||||
console.log(arr);
|
||||
function splitCJKV(arr, clo) {
|
||||
var result = [];
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
var item = arr[i];
|
||||
if (!Array.isArray(item)) {
|
||||
console.log(item.split(cjkvRegexPattern));
|
||||
result = result.concat(item.split(cjkvRegexPattern));
|
||||
result = result.concat(item.split(exports.cjkvRegexPattern));
|
||||
}
|
||||
else {
|
||||
result.push(item);
|
||||
}
|
||||
}
|
||||
console.log(result);
|
||||
return result;
|
||||
}
|
||||
exports.splitCJKV = splitCJKV;
|
||||
/**
|
||||
* hyphenation for a clo document
|
||||
* @param arr the array for a `tkTree`
|
||||
* @param clo the Clo object
|
||||
*/
|
||||
function hyphenForClo(arr, clo) {
|
||||
let hyphenLanguage = clo.attrs["hyphenLanguage"];
|
||||
let res = hyphenTkTree(arr, hyphenLanguage);
|
||||
return res;
|
||||
}
|
||||
exports.hyphenForClo = hyphenForClo;
|
||||
/**
|
||||
* convert spaces to Breakpoint
|
||||
* \s+ => ["bp" [\s+] ""]
|
||||
* @param arr the tkTree input text stream
|
||||
* @param clo the Clo object
|
||||
* @returns the converted object
|
||||
*/
|
||||
function spacesToBreakpoint(arr, clo) {
|
||||
let spacePattern = /^([ \t]+)$/g;
|
||||
var result = [];
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
var item = arr[i];
|
||||
if (!Array.isArray(item) && item.match(spacePattern)) {
|
||||
result.push(['bp', item, ""]); // push a newline command to the result `tkTree`
|
||||
}
|
||||
else {
|
||||
result.push(item);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
exports.spacesToBreakpoint = spacesToBreakpoint;
|
||||
/**
|
||||
* remove all the `` (empty string) in the arr
|
||||
* @param arr the tkTree to be filtered
|
||||
* @param clo the Clo file
|
||||
*/
|
||||
function filterEmptyString(arr, clo) {
|
||||
if (Array.isArray(arr)) {
|
||||
arr.filter((x) => { return x != ``; });
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
exports.filterEmptyString = filterEmptyString;
|
||||
/**
|
||||
* OTHER FUNCTIONS
|
||||
*/
|
||||
/**
|
||||
* hyphenate for a tkTree
|
||||
* - hyphenation => ["bp", "", "-"]
|
||||
* @param arr the tkTree array
|
||||
* @param lang ISO 639 code for the language
|
||||
*/
|
||||
function hyphenTkTree(arr, lang) {
|
||||
// import corresponding hyphen language data and function
|
||||
let hyphen = require("hyphen/" + lang);
|
||||
let result = [];
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let element = arr[i];
|
||||
let splitter = "分"; // a CJKV
|
||||
if (!Array.isArray(element)) {
|
||||
let hyphenatedElement = hyphen.hyphenateSync(element, { hyphenChar: splitter });
|
||||
let hyphenatedSplitted = hyphenatedElement.split(splitter);
|
||||
var newSplitted = [];
|
||||
for (var j = 0; j < hyphenatedSplitted.length - 1; j++) {
|
||||
newSplitted.push(hyphenatedSplitted[j]);
|
||||
// "bp" for breakpoint
|
||||
newSplitted.push(["bp", "", "-"]); //insert a breakable point (bp) mark
|
||||
}
|
||||
newSplitted.push(hyphenatedSplitted[hyphenatedSplitted.length - 1]);
|
||||
result = result.concat(newSplitted);
|
||||
}
|
||||
else {
|
||||
result.push(element);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
exports.hyphenTkTree = hyphenTkTree;
|
||||
/**
|
||||
* calculate the text width and Height with a given `TextStyle`
|
||||
* @param preprocessed
|
||||
* @param defaultFontStyle
|
||||
*/
|
||||
function calculateTextWidthHeight(preprocessed, style) {
|
||||
var dom = new jsdom_1.JSDOM(`<!DOCTYPE html><html><head></head>
|
||||
<body><canvas id="canvas"></canvas></body></html>`);
|
||||
try {
|
||||
let canvas = dom.window.document.getElementById("canvas");
|
||||
console.log(canvas);
|
||||
/*if (!(canvas instanceof HTMLElement)){
|
||||
throw new Error('the <canvas="canvas"> in the jsdom\'s DOM is not found.');
|
||||
|
||||
}*/
|
||||
let context = canvas.getContext("2d");
|
||||
console.log(context);
|
||||
if (context == null) {
|
||||
throw new Error('`canvas.getContext("2d");` can\'t be executed.');
|
||||
}
|
||||
context.font = `normal normal 10pt ${style.family}`;
|
||||
console.log(context.font);
|
||||
let txt = `Hello john`;
|
||||
console.log(txt);
|
||||
let measured = context.measureText(txt);
|
||||
let width = measured.width;
|
||||
let height = measured.actualBoundingBoxAscent;
|
||||
let depth = measured.actualBoundingBoxDescent;
|
||||
console.log("width: " + width);
|
||||
console.log("height: " + height);
|
||||
console.log("depth: " + depth);
|
||||
}
|
||||
catch (error) {
|
||||
console.log("Exception " + error);
|
||||
}
|
||||
}
|
||||
exports.calculateTextWidthHeight = calculateTextWidthHeight;
|
||||
/**
|
||||
* whole document-representing class
|
||||
*/
|
||||
class Clo {
|
||||
constructor() {
|
||||
this.preprocessors = [];
|
||||
this.mainStream = [];
|
||||
this.attributes = { "page": A4_IN_PX };
|
||||
this.attrs = {
|
||||
"page": exports.A4_IN_PX,
|
||||
"defaultFrameStyle": exports.defaultFrameStyle,
|
||||
"hyphenLanguage": 'en' // hyphenated in the language (in ISO 639)
|
||||
};
|
||||
// register the precessor functions
|
||||
this.preprocessorRegister(splitCJKV);
|
||||
this.preprocessorRegister(hyphenForClo);
|
||||
this.preprocessorRegister(twoReturnsToNewline);
|
||||
this.preprocessorRegister(spacesToBreakpoint);
|
||||
this.preprocessorRegister(filterEmptyString);
|
||||
}
|
||||
setAttr(attr, val) {
|
||||
Object.assign(this.attributes, attr, val);
|
||||
Object.assign(this.attrs, attr, val);
|
||||
}
|
||||
getAttr(attr) {
|
||||
if (Object.keys(this.attributes).length === 0) {
|
||||
return this.attributes[attr];
|
||||
if (Object.keys(this.attrs).length === 0) {
|
||||
return this.attrs[attr];
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
|
@ -107,14 +277,18 @@ class Clo {
|
|||
}
|
||||
generatePdf() {
|
||||
// preprocessed
|
||||
var prepro = this.mainStream;
|
||||
var preprocessed = this.mainStream;
|
||||
for (var i = 0; i < this.preprocessors.length; i++) {
|
||||
prepro = this.preprocessors[i](prepro);
|
||||
preprocessed = this.preprocessors[i](preprocessed, this);
|
||||
}
|
||||
// generate the width and height of the stream
|
||||
let defaultFontStyle = this.attrs["defaultFrameStyle"].textStyle;
|
||||
calculateTextWidthHeight(preprocessed, defaultFontStyle);
|
||||
// TODO
|
||||
console.log("test" + prepro);
|
||||
console.log(preprocessed);
|
||||
}
|
||||
}
|
||||
exports.Clo = Clo;
|
||||
exports.a = new Clo();
|
||||
exports.default = exports.a;
|
||||
/*
|
||||
export let a = new Clo();
|
||||
export default a; */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { isKeyObject, isStringObject } from "util/types";
|
||||
import {tkTree} from "../parser";
|
||||
import {TextStyle, FontStyle, TextWeight} from "../canva";
|
||||
import { isString } from "util";
|
||||
import {FontStyle, TextStyle, TextWeight} from "../canva";
|
||||
import { JSDOM } from "jsdom";
|
||||
|
||||
/**
|
||||
* TYPES
|
||||
|
@ -13,7 +13,7 @@ import { isString } from "util";
|
|||
* TTB - top to bottom
|
||||
* etc.
|
||||
*/
|
||||
enum Direction{
|
||||
export enum Direction{
|
||||
LTR,
|
||||
RTL,
|
||||
TTB,
|
||||
|
@ -25,18 +25,24 @@ enum Direction{
|
|||
* - directionInsideLine : text direction inside a line
|
||||
* - baselineskip : the distance between baselines in px
|
||||
*/
|
||||
interface FrameBox extends Box{
|
||||
export interface FrameBox extends Box{
|
||||
directionInsideLine : Direction,
|
||||
baseLineskip : number | null,
|
||||
}
|
||||
|
||||
/**
|
||||
* a basic Box
|
||||
* - x :
|
||||
* - y :
|
||||
* - textStyle :
|
||||
* - direction :
|
||||
* - width :
|
||||
* - content :
|
||||
*/
|
||||
interface Box{
|
||||
export interface Box{
|
||||
x : number | null,
|
||||
y : number | null,
|
||||
fontStyle : FontStyle | null,
|
||||
textStyle : TextStyle | null,
|
||||
direction : Direction,
|
||||
width : number,
|
||||
height : number,
|
||||
|
@ -47,21 +53,21 @@ interface Box{
|
|||
/**
|
||||
* DEFAULT CONST PART
|
||||
*/
|
||||
const A4_IN_PX = {"width" : 793.7,
|
||||
export const A4_IN_PX = {"width" : 793.7,
|
||||
"height" : 1122.5};
|
||||
|
||||
const defaultTextStyle : FontStyle = {
|
||||
family : "FreeSans",
|
||||
size : 12,
|
||||
export const defaultTextStyle : TextStyle = {
|
||||
family : "FreeSerif",
|
||||
size : ptToPx(12),
|
||||
textWeight : TextWeight.REGULAR,
|
||||
textStyle : TextStyle.ITALIC,
|
||||
fontStyle : FontStyle.ITALIC,
|
||||
}
|
||||
|
||||
const defaultFrameStyle : FrameBox = {
|
||||
export const defaultFrameStyle : FrameBox = {
|
||||
directionInsideLine : Direction.LTR,
|
||||
direction : Direction.TTB,
|
||||
baseLineskip : ptToPx(15),
|
||||
fontStyle : defaultTextStyle,
|
||||
textStyle : defaultTextStyle,
|
||||
x : A4_IN_PX.width * 0.10,
|
||||
y : A4_IN_PX.height * 0.10,
|
||||
width : A4_IN_PX.width * 0.80,
|
||||
|
@ -69,9 +75,17 @@ const defaultFrameStyle : FrameBox = {
|
|||
content : null,
|
||||
};
|
||||
|
||||
const cjkvBlocksInRegex = ["Hani"];
|
||||
/**
|
||||
* definition for cjk scripts
|
||||
* - Hani : Han Character
|
||||
* - Hang : Hangul
|
||||
* - Bopo : Bopomofo
|
||||
* - Kana : Katakana
|
||||
* - Hira : Hiragana
|
||||
*/
|
||||
export const cjkvBlocksInRegex = ["Hani", "Hang", "Bopo", "Kana", "Hira"];
|
||||
|
||||
const cjkvRegexPattern = new RegExp("((?:" +
|
||||
export const cjkvRegexPattern = new RegExp("((?:" +
|
||||
cjkvBlocksInRegex.map((x)=>"\\p{Script_Extensions="+x+"}").join("|") + ")+)", "gu");
|
||||
/**
|
||||
* FUNCTION PART
|
||||
|
@ -81,8 +95,8 @@ const cjkvRegexPattern = new RegExp("((?:" +
|
|||
* @param pt pt size value
|
||||
* @returns the corresponding px value
|
||||
*/
|
||||
function ptToPx(pt : number) : number{
|
||||
return pt * 4 / 3.0;
|
||||
export function ptToPx(pt : number) : number{
|
||||
return pt * 4.0 / 3.0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -91,19 +105,54 @@ function ptToPx(pt : number) : number{
|
|||
* REGISTER PART
|
||||
*/
|
||||
|
||||
/**
|
||||
* convert '\n\n' to newline command ["nl"]
|
||||
* @param arr the input `tkTree`
|
||||
* @param clo the `Clo` object
|
||||
* @returns the input tktree
|
||||
*/
|
||||
export function twoReturnsToNewline(arr : tkTree, clo : Clo): tkTree{
|
||||
var middle : tkTree = [];
|
||||
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
var item = arr[i];
|
||||
if (!Array.isArray(item)){
|
||||
middle = middle.concat(item.split(/(\n\n)/g));
|
||||
}
|
||||
else{
|
||||
middle.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
var result : tkTree = [];
|
||||
for (let j = 0; j < middle.length; j++){
|
||||
var item = middle[j];
|
||||
if (!Array.isArray(item) && item == "\n\n"){
|
||||
result.push(["nl"]); // push a newline command to the result `tkTree`
|
||||
}
|
||||
else{
|
||||
result.push(middle[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* split CJKV and non-CJKV
|
||||
*
|
||||
* @param arr : input tkTree
|
||||
* @returns
|
||||
* @returns a splitted tkTree (by CJK and NonCJK)
|
||||
* - Examples:
|
||||
* ```
|
||||
* [`many臺中daylight`] => [`many`, `臺中`, `dahylight`]
|
||||
* ```
|
||||
*/
|
||||
function splitCJKV(arr : tkTree): tkTree{
|
||||
export function splitCJKV(arr : tkTree, clo : Clo): tkTree{
|
||||
var result : tkTree = [];
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
var item = arr[i];
|
||||
if (!Array.isArray(item)){
|
||||
console.log(item.split(cjkvRegexPattern));
|
||||
result = result.concat(item.split(cjkvRegexPattern));
|
||||
}
|
||||
else{
|
||||
|
@ -114,30 +163,182 @@ function splitCJKV(arr : tkTree): tkTree{
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* hyphenation for a clo document
|
||||
* @param arr the array for a `tkTree`
|
||||
* @param clo the Clo object
|
||||
*/
|
||||
export function hyphenForClo(arr : tkTree, clo : Clo): tkTree{
|
||||
let hyphenLanguage : string = clo.attrs["hyphenLanguage"];
|
||||
let res = hyphenTkTree(arr, hyphenLanguage);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* convert spaces to Breakpoint
|
||||
* \s+ => ["bp" [\s+] ""]
|
||||
* @param arr the tkTree input text stream
|
||||
* @param clo the Clo object
|
||||
* @returns the converted object
|
||||
*/
|
||||
export function spacesToBreakpoint(arr : tkTree, clo : Clo) : tkTree{
|
||||
let spacePattern = /^([ \t]+)$/g;
|
||||
var result : tkTree = [];
|
||||
for (let i = 0; i < arr.length; i++){
|
||||
var item = arr[i];
|
||||
if (!Array.isArray(item) && item.match(spacePattern)){
|
||||
result.push([ 'bp', item, "" ]); // push a newline command to the result `tkTree`
|
||||
}
|
||||
else{
|
||||
result.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove all the `` (empty string) in the arr
|
||||
* @param arr the tkTree to be filtered
|
||||
* @param clo the Clo file
|
||||
*/
|
||||
export function filterEmptyString(arr : tkTree, clo : Clo) : tkTree{
|
||||
if (Array.isArray(arr)){
|
||||
arr.filter((x)=>{return x != ``;});
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* OTHER FUNCTIONS
|
||||
*/
|
||||
|
||||
/**
|
||||
* hyphenate for a tkTree
|
||||
* - hyphenation => ["bp", "", "-"]
|
||||
* @param arr the tkTree array
|
||||
* @param lang ISO 639 code for the language
|
||||
*/
|
||||
export function hyphenTkTree(arr : tkTree, lang: string) : tkTree{
|
||||
// import corresponding hyphen language data and function
|
||||
let hyphen = require("hyphen/"+lang);
|
||||
|
||||
let result :tkTree[] = [];
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let element = arr[i];
|
||||
let splitter = "分"; // a CJKV
|
||||
if (!Array.isArray(element)){
|
||||
let hyphenatedElement : string = hyphen.hyphenateSync(element, {hyphenChar :splitter});
|
||||
let hyphenatedSplitted : tkTree = hyphenatedElement.split(splitter);
|
||||
var newSplitted : tkTree = [];
|
||||
for (var j=0; j<hyphenatedSplitted.length-1;j++){
|
||||
newSplitted.push(hyphenatedSplitted[j]);
|
||||
// "bp" for breakpoint
|
||||
newSplitted.push(["bp", "", "-"]); //insert a breakable point (bp) mark
|
||||
}
|
||||
newSplitted.push(hyphenatedSplitted[hyphenatedSplitted.length-1]);
|
||||
|
||||
result = result.concat(newSplitted);
|
||||
|
||||
}else{
|
||||
result.push(element);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate the text width and Height with a given `TextStyle`
|
||||
* @param preprocessed
|
||||
* @param defaultFontStyle
|
||||
*/
|
||||
export function calculateTextWidthHeight(preprocessed : tkTree, style : TextStyle): void {
|
||||
var dom = new JSDOM(`<!DOCTYPE html><html><head></head>
|
||||
<body><canvas id="canvas"></canvas></body></html>`);
|
||||
|
||||
try {
|
||||
let canvas = dom.window.document.getElementById("canvas");
|
||||
console.log(canvas);
|
||||
|
||||
/*if (!(canvas instanceof HTMLElement)){
|
||||
throw new Error('the <canvas="canvas"> in the jsdom\'s DOM is not found.');
|
||||
|
||||
}*/
|
||||
|
||||
let context = (<HTMLCanvasElement>canvas).getContext("2d");
|
||||
console.log(context);
|
||||
if (context == null){
|
||||
throw new Error('`canvas.getContext("2d");` can\'t be executed.');
|
||||
|
||||
}
|
||||
|
||||
context.font = `normal normal ${style.size}px ${style.family}`;
|
||||
console.log(context.font);
|
||||
let txt = `Hello john`;
|
||||
console.log(txt);
|
||||
let measured = context.measureText(txt);
|
||||
let width = measured.width;
|
||||
let height = measured.actualBoundingBoxAscent;
|
||||
let depth = measured.actualBoundingBoxDescent;
|
||||
|
||||
console.log("width: "+width);
|
||||
console.log("height: "+height);
|
||||
console.log("depth: "+depth);
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.log("Exception "+error);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* whole document-representing class
|
||||
*/
|
||||
export class Clo{
|
||||
/** storing the text string into the main frame */
|
||||
mainStream : Array<string>;
|
||||
/** array of preprocessor functions to preprocess the `mainStream` */
|
||||
preprocessors : Array<Function>;
|
||||
attributes: {[index: string]:any} ; // a4 size(x,y)
|
||||
/** the attributes for the Clo */
|
||||
attrs: {[index: string]:any} ; // a4 size(x,y)
|
||||
|
||||
|
||||
constructor(){
|
||||
this.preprocessors = [];
|
||||
this.mainStream = [];
|
||||
this.attributes = {"page" : A4_IN_PX};
|
||||
this.attrs = {
|
||||
"page" : A4_IN_PX, // default for a4. in px of [x, y]
|
||||
"defaultFrameStyle" : defaultFrameStyle, // defaultFrameStyle
|
||||
"hyphenLanguage" : 'en' // hyphenated in the language (in ISO 639)
|
||||
};
|
||||
|
||||
|
||||
|
||||
// register the precessor functions
|
||||
this.preprocessorRegister(splitCJKV);
|
||||
this.preprocessorRegister(hyphenForClo);
|
||||
this.preprocessorRegister(twoReturnsToNewline);
|
||||
this.preprocessorRegister(spacesToBreakpoint);
|
||||
this.preprocessorRegister(filterEmptyString);
|
||||
}
|
||||
|
||||
public setAttr(attr : string, val : any):void{
|
||||
Object.assign(this.attributes, attr, val);
|
||||
Object.assign(this.attrs, attr, val);
|
||||
}
|
||||
|
||||
public getAttr(attr:string) : any{
|
||||
if (Object.keys(this.attributes).length === 0){
|
||||
return this.attributes[attr];
|
||||
if (Object.keys(this.attrs).length === 0){
|
||||
return this.attrs[attr];
|
||||
}else{
|
||||
return undefined;
|
||||
}
|
||||
|
@ -154,16 +355,22 @@ export class Clo{
|
|||
|
||||
public generatePdf(){
|
||||
// preprocessed
|
||||
var prepro = this.mainStream;
|
||||
var preprocessed = this.mainStream;
|
||||
for (var i = 0; i<this.preprocessors.length; i++){
|
||||
prepro = this.preprocessors[i](prepro);
|
||||
preprocessed = this.preprocessors[i](preprocessed, this);
|
||||
}
|
||||
// generate the width and height of the stream
|
||||
|
||||
let defaultFontStyle : TextStyle = this.attrs["defaultFrameStyle"].textStyle;
|
||||
calculateTextWidthHeight(preprocessed, defaultFontStyle);
|
||||
|
||||
// TODO
|
||||
console.log("test"+prepro);
|
||||
console.log(preprocessed);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
export let a = new Clo();
|
||||
export default a;
|
||||
export default a; */
|
|
@ -33,7 +33,7 @@ export function tkTreeToSExp(t: tkTree): string{
|
|||
|
||||
export type tkTree = string | tkTree[];
|
||||
|
||||
enum TokenKind {
|
||||
export enum TokenKind {
|
||||
Seperator, // ---
|
||||
Semicolon, // ;
|
||||
Number,
|
||||
|
@ -50,7 +50,7 @@ enum TokenKind {
|
|||
/**
|
||||
* Parsing
|
||||
*/
|
||||
const lexer = p.buildLexer([
|
||||
export const lexer = p.buildLexer([
|
||||
[true, /^\d+(\.\d+)?/g, TokenKind.Number],
|
||||
[true, /^[\\][\\]/g, TokenKind.Op],
|
||||
[true, /^\\\@/g, TokenKind.ExcapeAt],
|
||||
|
@ -75,41 +75,42 @@ const lexer = p.buildLexer([
|
|||
|
||||
|
||||
|
||||
const PROG = p.rule<TokenKind, tkTree>();
|
||||
const SEGMENT = p.rule<TokenKind, tkTree>();
|
||||
const IMPORT = p.rule<TokenKind, tkTree>();
|
||||
const IMPORTS = p.rule<TokenKind, tkTree>();
|
||||
const SEMICOLON = p.rule<TokenKind, tkTree>();
|
||||
const NOT_AT_TEXT = p.rule<TokenKind, tkTree>();
|
||||
const CONTENT = p.rule<TokenKind, tkTree>();
|
||||
export const PROG = p.rule<TokenKind, tkTree>();
|
||||
export const SEGMENT = p.rule<TokenKind, tkTree>();
|
||||
export const IMPORT = p.rule<TokenKind, tkTree>();
|
||||
export const IMPORTS = p.rule<TokenKind, tkTree>();
|
||||
export const SEMICOLON = p.rule<TokenKind, tkTree>();
|
||||
export const NOT_AT_TEXT = p.rule<TokenKind, tkTree>();
|
||||
export const CONTENT = p.rule<TokenKind, tkTree>();
|
||||
|
||||
|
||||
function applySegment(input: [Token<TokenKind>, Token<TokenKind>[],
|
||||
export function applySegment(input: [Token<TokenKind>, Token<TokenKind>[],
|
||||
Token<TokenKind>]): tkTree[]{
|
||||
let unpackedInnerExprs = input[1].map((x)=>{return x.text});
|
||||
return ["%exprs", unpackedInnerExprs];
|
||||
}
|
||||
|
||||
function applySemiColon(value: Token<TokenKind.Semicolon>): tkTree{
|
||||
export function applySemiColon(value: Token<TokenKind.Semicolon>): tkTree{
|
||||
return value.text;
|
||||
}
|
||||
|
||||
function applyParts(first: tkTree,
|
||||
second: [Token<TokenKind>, tkTree]):tkTree {
|
||||
return ["%clo", first , second[1]];
|
||||
export function applyParts(first: tkTree,
|
||||
second: [Token<TokenKind>, Token<TokenKind>, tkTree]):tkTree {
|
||||
return ["%clo", first , second[2]];
|
||||
}
|
||||
|
||||
function applyPartsWithoutImport(parsed: [Token<TokenKind>, tkTree]):tkTree {
|
||||
return ["%clo", "" , parsed[1]];
|
||||
export function applyPartsWithoutImport(
|
||||
parsed: [Token<TokenKind>, Token<TokenKind>, tkTree]):tkTree {
|
||||
return ["%clo", "" , parsed[2]];
|
||||
}
|
||||
|
||||
|
||||
function applyComment(value: Token<TokenKind.Comment>): tkTree[]{
|
||||
export function applyComment(value: Token<TokenKind.Comment>): tkTree[]{
|
||||
return [value.text];
|
||||
}
|
||||
|
||||
|
||||
function applyImport(input: [Token<TokenKind>,Token<TokenKind>[], tkTree]) : tkTree{
|
||||
export function applyImport(input: [Token<TokenKind>,Token<TokenKind>[], tkTree]) : tkTree{
|
||||
let importTail = input[1].map(x=>x.text);
|
||||
return ["import"].concat(importTail);
|
||||
};
|
||||
|
@ -123,7 +124,7 @@ function applyImportComment(input: [Token<TokenKind>,Token<TokenKind>[],
|
|||
return ["import"].concat(importTail).concat(comment);
|
||||
};*/
|
||||
|
||||
function applyImports(input : [tkTree, tkTree[]]): tkTree{
|
||||
export function applyImports(input : [tkTree, tkTree[]]): tkTree{
|
||||
let resultBody = [input[0]].concat(input[1]);
|
||||
let resultWrapper = ["%import", resultBody];
|
||||
return resultWrapper;
|
||||
|
@ -132,29 +133,29 @@ function applyImports(input : [tkTree, tkTree[]]): tkTree{
|
|||
|
||||
|
||||
|
||||
function applyNotAtText(value : Token<TokenKind>): tkTree{
|
||||
export function applyNotAtText(value : Token<TokenKind>): tkTree{
|
||||
if (value.text == "\\\@"){
|
||||
return '@';
|
||||
}
|
||||
else{return value.text;}
|
||||
};
|
||||
|
||||
function applyText (input : tkTree): tkTree[]{
|
||||
export function applyText (input : tkTree): tkTree[]{
|
||||
return ["%text", input];
|
||||
};
|
||||
|
||||
function applyContent(input : tkTree[]): tkTree[]{
|
||||
export function applyContent(input : tkTree[]): tkTree[]{
|
||||
return ["%content", input];
|
||||
};
|
||||
|
||||
function applySpaceNL(value : Token<TokenKind.SpaceNL>): tkTree{
|
||||
export function applySpaceNL(value : Token<TokenKind.SpaceNL>): tkTree{
|
||||
return value.text;
|
||||
}
|
||||
|
||||
/**
|
||||
* IMPORTEE: Number, Op, Paren, Id, Str, Comment,
|
||||
*/
|
||||
let IMPORTEE = p.alt(p.tok(TokenKind.Number),
|
||||
export let IMPORTEE = p.alt(p.tok(TokenKind.Number),
|
||||
p.tok(TokenKind.Op),
|
||||
p.tok(TokenKind.Paren),
|
||||
p.tok(TokenKind.Id),
|
||||
|
@ -162,7 +163,7 @@ let IMPORTEE = p.alt(p.tok(TokenKind.Number),
|
|||
p.tok(TokenKind.SpaceNL),
|
||||
p.tok(TokenKind.Comment));
|
||||
|
||||
let NOT_AT = p.alt(p.tok(TokenKind.Seperator),
|
||||
export let NOT_AT = p.alt(p.tok(TokenKind.Seperator),
|
||||
p.tok(TokenKind.Semicolon),
|
||||
p.tok(TokenKind.Number),
|
||||
p.tok(TokenKind.ExcapeAt),
|
||||
|
@ -175,12 +176,12 @@ let NOT_AT = p.alt(p.tok(TokenKind.Seperator),
|
|||
);
|
||||
|
||||
/**
|
||||
* PROG : IMPORTS '---' CONTENT | '---' CONTNENT
|
||||
* PROG : IMPORTS '---' NEWLINE CONTENT | '---' NEWLINE CONTNENT
|
||||
*/
|
||||
PROG.setPattern(
|
||||
p.alt(
|
||||
p.lrec_sc(IMPORTS, p.seq(p.str('---'), CONTENT), applyParts),
|
||||
p.apply(p.seq(p.str('---'), CONTENT), applyPartsWithoutImport))
|
||||
p.lrec_sc(IMPORTS, p.seq(p.str('---'), p.str("\n"), CONTENT), applyParts),
|
||||
p.apply(p.seq(p.str('---'), p.str("\n"), CONTENT), applyPartsWithoutImport))
|
||||
|
||||
)
|
||||
|
||||
|
@ -242,7 +243,7 @@ CONTENT.setPattern(
|
|||
/**
|
||||
* the head part of the output JS code : before import
|
||||
*/
|
||||
let outputHead = `
|
||||
export let outputHead = `
|
||||
/* clo, a typesetting engine, generated JS file*/
|
||||
/* CLO: beginning of head*/
|
||||
|
||||
|
@ -254,11 +255,15 @@ let clo = new cloLib.Clo();
|
|||
/**
|
||||
* the middle part of the output JS code : between import part and content part
|
||||
*/
|
||||
let outputMiddle =`
|
||||
export let outputMiddle =`
|
||||
/* CLO: beginning of middle part*/
|
||||
clo.mainStream = /* CLO: end of middle part*/
|
||||
`
|
||||
let outputEnd =`
|
||||
|
||||
/**
|
||||
* the end part of the output JS code : after content part
|
||||
*/
|
||||
export let outputEnd =`
|
||||
/* CLO: beginning of end part*/
|
||||
clo.generatePdf();
|
||||
/*CLO : end of end part*/
|
||||
|
@ -346,6 +351,9 @@ export function treeToJS(tree : tkTree): string{
|
|||
* `inputText` to `tkTree` (ASTTree)
|
||||
*/
|
||||
export function inputTextToTree(inputText : string){
|
||||
return p.expectSingleResult(
|
||||
p.expectEOF(PROG.parse(lexer.parse(inputText))));
|
||||
// force convert Windows newline to Linux newline
|
||||
inputText = inputText.replace("\r\n", "\n");
|
||||
|
||||
return p.expectSingleResult(
|
||||
p.expectEOF(PROG.parse(lexer.parse(inputText))));
|
||||
}
|
|
@ -1,33 +1,30 @@
|
|||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.pdfGenerate = void 0;
|
||||
const fs_1 = require("fs");
|
||||
const pdf_lib_1 = require("pdf-lib");
|
||||
/*import { readFileSync, writeFileSync } from "fs";
|
||||
import { PDFDocument } from "pdfkit";
|
||||
var fontkit = require('pdf-fontkit');
|
||||
function pdfGenerate() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const pdfDoc = yield pdf_lib_1.PDFDocument.create();
|
||||
const page = pdfDoc.addPage();
|
||||
pdfDoc.registerFontkit(fontkit);
|
||||
const fontBytes = (0, fs_1.readFileSync)("/usr/share/fonts/uming.ttf");
|
||||
const font2 = yield pdfDoc.embedFont(fontBytes, { subset: true });
|
||||
const fontBytes2 = (0, fs_1.readFileSync)("/usr/share/fonts/truetype/noto/NotoSansArabic-Light.ttf");
|
||||
const font3 = yield pdfDoc.embedFont(fontBytes2, { subset: true });
|
||||
page.drawText("x=20, y=20", { x: 20, y: 20 });
|
||||
page.drawText("x:20, y:100 天地人", { x: 20, y: 100, font: font2 });
|
||||
page.drawText("عربي", { x: 50, y: 150, font: font3 });
|
||||
const pdfBytes = yield pdfDoc.save();
|
||||
(0, fs_1.writeFileSync)('/tmp/test2.pdf', pdfBytes);
|
||||
});
|
||||
|
||||
export async function pdfGenerate(){
|
||||
|
||||
const pdfDoc = await PDFDocument.create()
|
||||
const page = pdfDoc.addPage()
|
||||
|
||||
pdfDoc.registerFontkit(fontkit);
|
||||
const fontBytes = readFileSync("/usr/share/fonts/uming.ttf");
|
||||
const font2 = await pdfDoc.embedFont(fontBytes, {subset:true})
|
||||
|
||||
const fontBytes2 = readFileSync("/usr/share/fonts/truetype/noto/NotoSansArabic-Light.ttf")
|
||||
|
||||
const font3 = await pdfDoc.embedFont(fontBytes2, {subset:true})
|
||||
|
||||
page.drawText("x=20, y=20", {x : 20, y : 20})
|
||||
page.drawText("x:20, y:100 天地人", {x : 20, y : 100, font: font2})
|
||||
page.drawText("عربي", {x : 50, y : 150, font: font3})
|
||||
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
|
||||
writeFileSync('/tmp/test2.pdf', pdfBytes);
|
||||
}
|
||||
exports.pdfGenerate = pdfGenerate;
|
||||
|
||||
pdfGenerate();
|
||||
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { readFileSync, writeFileSync } from "fs";
|
||||
import { PDFDocument } from "pdf-lib";
|
||||
/*import { readFileSync, writeFileSync } from "fs";
|
||||
import { PDFDocument } from "pdfkit";
|
||||
var fontkit = require('pdf-fontkit');
|
||||
|
||||
export async function pdfGenerate(){
|
||||
|
@ -24,4 +24,6 @@ export async function pdfGenerate(){
|
|||
writeFileSync('/tmp/test2.pdf', pdfBytes);
|
||||
}
|
||||
|
||||
pdfGenerate();
|
||||
pdfGenerate();
|
||||
|
||||
*/
|
|
@ -6,21 +6,21 @@ let hanziFont = {
|
|||
family : "Noto Sans CJK TC",
|
||||
size : 12,
|
||||
textWeight : canva.TextWeight.REGULAR,
|
||||
textStyle : canva.TextStyle.ITALIC,
|
||||
fontStyle : canva.FontStyle.ITALIC,
|
||||
}
|
||||
|
||||
let romanFont = {
|
||||
family : "FreeSans",
|
||||
size : 15,
|
||||
textWeight : canva.TextWeight.BOLD,
|
||||
textStyle : canva.TextStyle.ITALIC,
|
||||
fontStyle : canva.FontStyle.ITALIC,
|
||||
}
|
||||
|
||||
let arabicFont = {
|
||||
family : "noto sans arabic",
|
||||
size : 16,
|
||||
textWeight : canva.TextWeight.REGULAR,
|
||||
textStyle : canva.TextStyle.NORMAL,
|
||||
fontStyle : canva.FontStyle.NORMAL,
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,7 +32,7 @@ async function foo (){
|
|||
|
||||
let clo = await {
|
||||
mainText : ["123 一隻貓跑過來"],
|
||||
mainFontStyle : hanziFont,
|
||||
mainTextStyle : hanziFont,
|
||||
PDFCanvas : doc,
|
||||
|
||||
}
|
||||
|
|
34
參考資料-Harfbuzz如何使用.py
Normal file
34
參考資料-Harfbuzz如何使用.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
import sys
|
||||
|
||||
import uharfbuzz as hb
|
||||
|
||||
|
||||
fontfile = sys.argv[1]
|
||||
text = sys.argv[2]
|
||||
|
||||
blob = hb.Blob.from_file_path(fontfile)
|
||||
face = hb.Face(blob)
|
||||
font = hb.Font(face)
|
||||
|
||||
px = 96
|
||||
scale = 1000000.0/952997
|
||||
font.scale = (px *scale* 1024, px*scale * 1024)
|
||||
|
||||
buf = hb.Buffer()
|
||||
buf.add_str(text)
|
||||
buf.guess_segment_properties()
|
||||
|
||||
features = {"kern": True, "liga": True}
|
||||
hb.shape(font, buf, features)
|
||||
|
||||
infos = buf.glyph_infos
|
||||
positions = buf.glyph_positions
|
||||
|
||||
for info, pos in zip(infos, positions):
|
||||
gid = info.codepoint
|
||||
cluster = info.cluster
|
||||
x_advance = pos.x_advance / 1024
|
||||
y_advance = pos.y_advance / 1024
|
||||
x_offset = pos.x_offset / 1024
|
||||
y_offset = pos.y_offset /1024
|
||||
print(f"gid{gid}={cluster}@{x_advance},{y_offset}+{x_advance},{y_advance}")
|
Loading…
Reference in a new issue