Skip to content

Commit 4d02191

Browse files
committed
Restore the demo
Restore the demo from gh-pages branch, update it to current API, and automatically deploy it with the docs.
1 parent ca16eda commit 4d02191

3 files changed

Lines changed: 151 additions & 3 deletions

File tree

.github/workflows/docs.yml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
name: Docs
22

33
on:
4-
push:
4+
workflow_run:
5+
workflows: [ "Build" ]
56
branches: [ "main" ]
7+
types: [ completed ]
68

79
permissions:
810
contents: read
911
pages: write
1012
id-token: write
13+
actions: read
1114

1215
concurrency:
1316
group: "pages"
1417
cancel-in-progress: true
1518

1619
jobs:
17-
docs:
20+
deploy:
21+
if: github.event.workflow_run.conclusion == 'success'
1822
runs-on: ubuntu-latest
1923
environment:
2024
name: github-pages
@@ -23,6 +27,13 @@ jobs:
2327
- name: Checkout
2428
uses: actions/checkout@v4
2529

30+
- name: Download build artifacts
31+
uses: actions/download-artifact@v4
32+
with:
33+
name: wasm
34+
run-id: ${{ github.event.workflow_run.id }}
35+
github-token: ${{ github.token }}
36+
2637
- name: Setup Node.js
2738
uses: actions/setup-node@v4
2839
with:
@@ -31,6 +42,14 @@ jobs:
3142
- name: Generate docs
3243
run: make doc
3344

45+
- name: Build demo
46+
run: |
47+
npx tsdown
48+
mkdir -p docs/demo
49+
cp demo/index.html docs/demo/
50+
cp dist/index.mjs dist/harfbuzz.js dist/harfbuzz.wasm docs/demo/
51+
cp test/fonts/noto/NotoSans-Regular.ttf docs/demo/
52+
3453
- name: Setup Pages
3554
uses: actions/configure-pages@v4
3655

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
Providing [HarfBuzz](https://github.com/harfbuzz/harfbuzz) shaping
1212
library for client/server side JavaScript projects.
1313

14-
See the demo [here](https://harfbuzz.github.io/harfbuzzjs/).
14+
See the demo [here](https://harfbuzz.github.io/harfbuzzjs/demo/).
1515

1616
## Building
1717
1. Install emscripten

demo/index.html

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<meta charset="utf-8">
2+
<p><a href="https://github.com/harfbuzz/harfbuzzjs">harfbuzzjs</a> demo. Supports font drag and drop.</p>
3+
<p><input type="text" value="abc" id="text"></p>
4+
<p><a id="svgResult" href="#" title="Click to download"></a></p>
5+
<p>Result:<div id="shapeResult"></div></p>
6+
<script type="module">
7+
import harfbuzz from './index.mjs';
8+
const hb = await harfbuzz;
9+
10+
var fontBlob;
11+
function updateResult() {
12+
var blob = new hb.Blob(fontBlob);
13+
var face = new hb.Face(blob, 0);
14+
var font = new hb.Font(face);
15+
font.setScale(1000, 1000); // Optional, if not given will be in font upem
16+
17+
var buffer = new hb.Buffer();
18+
buffer.addText(text.value);
19+
buffer.guessSegmentProperties();
20+
// buffer.setDirection('ltr'); // optional as can be by guessSegmentProperties also
21+
hb.shape(font, buffer);
22+
var result = buffer.json();
23+
24+
// returns glyphs paths, totally optional
25+
var glyphs = {};
26+
result.forEach(function (x) {
27+
if (glyphs[x.g]) return;
28+
glyphs[x.g] = font.glyphToJson(x.g);
29+
});
30+
31+
var xmin = 10000;
32+
var xmax = -10000;
33+
var ymin = 10000;
34+
var ymax = -10000;
35+
var ax = 0;
36+
var ay = 0;
37+
var path = pathToRelative(result.map(function (x) {
38+
var result = glyphs[x.g].filter(function (command) {
39+
return command.type !== 'Z';
40+
}).map(function (command) {
41+
var result = command.values.map(function (p, i) {
42+
// apply ax/ay/dx/dy to coords
43+
return i % 2 ? -(p + ay + x.dy) : p + ax + x.dx;
44+
}).map(function (x, i) {
45+
// bbox calc
46+
if (i % 2) {
47+
if (x < ymin) ymin = x;
48+
if (x > ymax) ymax = x;
49+
} else {
50+
if (x < xmin) xmin = x;
51+
if (x > xmax) xmax = x;
52+
}
53+
return x;
54+
});
55+
return [command.type].concat(result);
56+
});
57+
ax += x.ax; ay += x.ay;
58+
return result;
59+
}).reduce((acc, val) => acc.concat(val), [])).map(x => x[0] + x.slice(1).join(' ')).join('').replace(/ -/g, '-');
60+
var width = xmax - xmin;
61+
var height = ymax - ymin;
62+
// pad it a bit
63+
var pad = Math.round(Math.min(width / 10, height / 10));
64+
xmin -= pad;
65+
ymin -= pad;
66+
width += pad * 2;
67+
height += pad * 2;
68+
69+
var bbox = xmin + ' ' + ymin + ' ' + width + ' ' + height;
70+
71+
svgResult.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="' + bbox + '">' +
72+
'<path d="' + path + '" /></svg>';
73+
svgResult.download = text.value + '.svg';
74+
// revoke previous URL
75+
if (svgResult.href) URL.revokeObjectURL(svgResult.href);
76+
svgResult.href = URL.createObjectURL(new Blob([svgResult.innerHTML.replace(' height="128"', '')], { type: 'text/plain' }));
77+
78+
shapeResult.innerText = JSON.stringify(result);
79+
}
80+
81+
fetch('NotoSans-Regular.ttf').then(function (res) {
82+
return res.arrayBuffer();
83+
}).then(function (blob) {
84+
fontBlob = new Uint8Array(blob);
85+
updateResult();
86+
});
87+
88+
document.getElementById('text').addEventListener('keyup', function(e) {
89+
updateResult();
90+
});
91+
92+
document.addEventListener('dragover', function (e) {
93+
e.stopPropagation(); e.preventDefault();
94+
}, false);
95+
document.addEventListener('dragleave', function (e) {
96+
e.stopPropagation(); e.preventDefault();
97+
}, false);
98+
document.addEventListener('drop', function (e) {
99+
e.stopPropagation(); e.preventDefault();
100+
handleFontUpdate(e.dataTransfer.files[0]);
101+
});
102+
103+
function handleFontUpdate(file) {
104+
if (!file) return;
105+
var reader = new FileReader();
106+
reader.addEventListener("load", function () {
107+
fontBlob = new Uint8Array(reader.result);
108+
updateResult();
109+
});
110+
reader.readAsArrayBuffer(file);
111+
}
112+
113+
// Totally optional, https://github.com/adobe-webplatform/Snap.svg/blob/7abe4d1/src/path.js#L532
114+
function pathToRelative(pathArray) {
115+
if (!pathArray.length) return [];
116+
var x = pathArray[0][1], y = pathArray[0][2];
117+
var prevCmd = '';
118+
return [["M", x, y]].concat(pathArray.slice(1).map(function (pa) {
119+
var r = [prevCmd === pa[0] ? ' ' : pa[0].toLowerCase()].concat(pa.slice(1).map(function (z, i) {
120+
return z - ((i % 2) ? y : x);
121+
}));
122+
var lastPoint = r.slice(-2);
123+
x += lastPoint[0];
124+
y += lastPoint[1];
125+
prevCmd = pa[0];
126+
return r;
127+
}));
128+
}
129+
</script>

0 commit comments

Comments
 (0)