Skip to content

Commit 3a8bb21

Browse files
committed
Added phonetics
1 parent 1b244fa commit 3a8bb21

34 files changed

+1218
-14323
lines changed

build/fonts.js renamed to build-fonts.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
let fs = require('fs');
2+
let path = require('path');
23

34
let fonts = {
45
'font-cmu-serif': [
@@ -216,7 +217,9 @@ async function main(){
216217
for(let font of fonts[key]){
217218
buff += parseFont(font);
218219
}
219-
fs.writeFileSync(`dist/${key}.css`, buff);
220+
const tgt = `dist/fonts/${key}.css`;
221+
fs.mkdirSync(path.dirname(tgt), { recursive: true });
222+
fs.writeFileSync(tgt, buff);
220223
}
221224
}
222225
main();

build-plugins.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ async function main() {
1717
// Plugins
1818

1919
// Dependencies
20-
const tasks = [...distPlugins];
20+
const tasks = [{dist:compressor.dist, src:compressor.src, lz:false}, ...distPlugins];
2121
for (let {src} of distPlugins) {
2222
//if (!src.endsWith('.js')) continue;
2323
let content = '' + fs.readFileSync(src);
@@ -26,7 +26,7 @@ async function main() {
2626
{dist, src, lz:dist.endsWith('.lz.js')}
2727
);
2828
}
29-
console.log(tasks);
29+
3030
for(let {src, dist} of tasks){
3131
const tgt = dist.slice(1);
3232
let text = ''+fs.readFileSync(src);

dist/caph-docs.min.js

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/caph-docs.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/components/katex.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,6 @@ span.katex{
3838
.caph-katex-display-parent{
3939
width:100%;
4040
text-align:center;
41+
overflow-x: scroll;
4142
}
4243
`);

dist/components/phonetics.js

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
2+
// spell-checker: words sampa alveolo postalveolar downstep conv noto pharyngealized rhotacized velarized linguolabial upstep
3+
4+
5+
caph.libraries.phonetics = (()=>{
6+
const raWiki = [
7+
["ɓ", "b_<", "b_<", "voiced bilabial implosive"],
8+
["ɖ", "d`", "d`", "voiced retroflex plosive"],
9+
["ɗ", "d_<", "d_<", "voiced alveolar implosive"],
10+
["ɡ", "g", "g", "voiced velar plosive"],
11+
["ɠ", "g_<", "g_<", "voiced velar implosive"],
12+
["ɦ", "h\\", "h\\", "voiced glottal fricative"],
13+
["ʝ", "j\\", "j\\", "voiced palatal fricative"],
14+
["ɭ", "l`", "l`", "retroflex lateral approximant"],
15+
["ɺ", "l\\", "l\\", "alveolar lateral flap"],
16+
["ɳ", "n`", "n`", "retroflex nasal"],
17+
["ɸ", "p\\", "p\\", "voiceless bilabial fricative"],
18+
["ɽ", "r`", "r`", "retroflex flap"],
19+
["ɹ", "r\\", "r\\", "alveolar approximant"],
20+
["ɻ", "r\\`", "r\\`", "retroflex approximant"],
21+
["ʂ", "s`", "s`", "voiceless retroflex fricative"],
22+
["ɕ", "s\\", "s\\", "voiceless alveolo-palatal fricative"],
23+
["ʈ", "t`", "t`", "voiceless retroflex plosive"],
24+
["ʋ", "v\\", "v\\", "labiodental approximant"],
25+
["ɧ", "x\\", "x\\", "voiceless palatal-velar fricative"],
26+
["ʐ", "z`", "z`", "voiced retroflex fricative"],
27+
["ʑ", "z\\", "z\\", "voiced alveolo-palatal fricative"],
28+
["ʙ", "B\\", "B\\", "bilabial trill"],
29+
["ɢ", "G\\", "G\\", "voiced uvular plosive"],
30+
["ʛ", "G\\_<", "G\\_<", "voiced uvular implosive"],
31+
["ʜ", "H\\", "H\\", "voiceless epiglottal fricative"],
32+
["ɨ̞", "I\\", "I\\", "near-close central unrounded vowel"],
33+
["ɪ̈", "I\\", "I\\", "near-close central unrounded vowel"],
34+
["ɟ", "J\\", "J\\", "voiced palatal plosive"],
35+
["ʄ", "J\\_<", "J\\_<", "voiced palatal implosive"],
36+
["ɮ", "K\\", "K\\", "voiced alveolar lateral fricative"],
37+
["ʟ", "L\\", "L\\", "velar lateral approximant"],
38+
["ɰ", "M\\", "M\\", "velar approximant"],
39+
["ɴ", "N\\", "N\\", "uvular nasal"],
40+
["ʘ", "O\\", "O\\", "bilabial click"],
41+
["ʀ", "R\\", "R\\", "uvular trill"],
42+
["ʊ̈", "U\\", "U\\", "near-close central rounded vowel"],
43+
["ʉ̞", "U\\", "U\\", "near-close central rounded vowel"],
44+
["ħ", "X\\", "X\\", "voiceless pharyngeal fricative"],
45+
["ˑ", ":\\", ":\\", "half long"],
46+
["ɘ", "@\\", "@\\", "close-mid central unrounded vowel"],
47+
["ɞ", "3\\", "3\\", "open-mid central rounded vowel"],
48+
["ɶ", "&", "&\\", "open front rounded vowel"],
49+
["ʕ", "?\\", "?\\", "voiced pharyngeal fricative"],
50+
["ʢ", "<\\", "<\\", "voiced epiglottal fricative"],
51+
["ʡ", ">\\", ">\\", "epiglottal plosive"],
52+
["ǃ", "!\\", "!\\", "postalveolar click"],
53+
["ꜜ", "!", "!", "downstep"],
54+
["ǁ", "|\\|\\", "|\\|\\", "alveolar lateral click"],
55+
["ǀ", "|\\", "|\\", "dental click"],
56+
["‖", "||", "||", "major intonation group"],
57+
["ǂ", "=\\", "=\\", "palatal click"],
58+
["‿", "-\\", "-\\", "linking mark"],
59+
["̈", "_\"", "_\"", "centralized"],
60+
["̟", "_+", "_+", "advanced"],
61+
["̠", "_-", "_-", "retracted"],
62+
["̌", "_/", "_/", "rising tone"],
63+
["̥", "_0", "_0", "voiceless"],
64+
["ʼ", "_>", "_>", "ejective"],
65+
["ˤ", "_?\\", "_?\\", "pharyngealized"],
66+
["̂", "_\\", "_\\", "falling tone"],
67+
["̯", "_^", "_^", "non-syllabic"],
68+
["̚", "_}", "_}", "no audible release"],
69+
["˞", "`", "`", "rhotacized"],
70+
["̃", "~", "~", "nasalized"],
71+
["̃", "~", "~", "nasalized"],
72+
["̃", "_~", "_~", "nasalized"],
73+
["̘", "_A", "_A", "advanced tongue root"],
74+
["̺", "_a", "_a", "apical"],
75+
[" ᷅", "_B_L", "_B_L", "low rising tone"],
76+
["̏", "_B", "_B", "extra low tone"],
77+
["̜", "_c", "_c", "less rounded"],
78+
["̪", "_d", "_d", "dental"],
79+
["̴", "_e", "_e", "velarized or pharyngealized; also see 5"],
80+
["↘", "<F>", "<F>", "global fall"],
81+
["ˠ", "_G", "_G", "velarized"],
82+
[" ᷄", "_H_T", "_H_T", "high rising tone"],
83+
["́", "_H", "_H", "high tone"],
84+
["ʰ", "_h", "_h", "aspirated"],
85+
["̰", "_k", "_k", "creaky voice"],
86+
["̀", "_L", "_L", "low tone"],
87+
["ˡ", "_l", "_l", "lateral release"],
88+
["̄", "_M", "_M", "mid tone"],
89+
["̻", "_m", "_m", "laminal"],
90+
["̼", "_N", "_N", "linguolabial"],
91+
["ⁿ", "_n", "_n", "nasal release"],
92+
["̹", "_O", "_O", "more rounded"],
93+
["̞", "_o", "_o", "lowered"],
94+
["̙", "_q", "_q", "retracted tongue root"],
95+
["↗", "<R>", "<R>", "global rise"],
96+
[" ᷈", "_R_F", "_R_F", "rising falling tone"],
97+
["̌", "_R", "_R", "rising tone"],
98+
["̂", "_F", "_F", "falling tone"],
99+
["̝", "_r", "_r", "raised"],
100+
["̋", "_T", "_T", "extra high tone"],
101+
["̤", "_t", "_t", "breathy voice"],
102+
["̬", "_v", "_v", "voiced"],
103+
["ʷ", "_w", "_w", "labialized"],
104+
["̆", "_X", "_X", "extra-short"],
105+
["̽", "_x", "_x", "mid-centralized"],
106+
["ꜛ", "^", "^", "upstep"],
107+
["ː", ":", ":", "long"],
108+
["|", "|", "|", "minor (foot) group"],
109+
["̩", "=", "=", "syllabic"],
110+
["̩", "=", "=", "syllabic"],
111+
["ˈ", "\"", "'", "primary stress"],
112+
["ˌ", "%", ",", "secondary stress"],
113+
["ə", "@", "@", "schwa"],
114+
["ʲ", "_j", "_j", "palatalized"],
115+
["æ", "{", "&", "near-open front unrounded vowel"],
116+
["ʉ", "}", "u\\", "close central rounded vowel"],
117+
["ʔ", "?", "?", "glottal stop"],
118+
["ɨ", "1", "1", "close central unrounded vowel"],
119+
["ø", "2", "2", "close-mid front rounded vowel"],
120+
["ɜ", "3", "3", "open-mid central unrounded vowel"],
121+
["ɾ", "4", "4", "alveolar flap"],
122+
["ɫ", "5", "5", "velarized alveolar lateral approximant; also see _e"],
123+
["ɐ", "6", "6", "near-open central vowel"],
124+
["ɤ", "7", "7", "close-mid back unrounded vowel"],
125+
["ɵ", "8", "8", "close-mid central rounded vowel"],
126+
["œ", "9", "9", "open-mid front rounded vowel"],
127+
["ɑ", "A", "A", "open back unrounded vowel"],
128+
["β", "B", "B", "voiced bilabial fricative"],
129+
["ç", "C", "C", "voiceless palatal fricative"],
130+
["ð", "D", "D", "voiced dental fricative"],
131+
["ɛ", "E", "E", "open-mid front unrounded vowel"],
132+
["ɱ", "F", "F", "labiodental nasal"],
133+
["ɣ", "G", "G", "voiced velar fricative"],
134+
["ɥ", "H", "H", "labial-palatal approximant"],
135+
["ɪ", "I", "I", "near-close front unrounded vowel"],
136+
["ɲ", "J", "J", "palatal nasal"],
137+
["ɬ", "K", "K", "voiceless alveolar lateral fricative"],
138+
["ʎ", "L", "L", "palatal lateral approximant"],
139+
["ɯ", "M", "M", "close back unrounded vowel"],
140+
["ŋ", "N", "N", "velar nasal"],
141+
["ɔ", "O", "O", "open-mid back rounded vowel"],
142+
["ɒ", "Q", "Q", "open back rounded vowel"],
143+
["ʁ", "R", "R", "voiced uvular fricative"],
144+
["ʃ", "S", "S", "voiceless postalveolar fricative"],
145+
["θ", "T", "T", "voiceless dental fricative"],
146+
["ʊ", "U", "U", "near-close back rounded vowel"],
147+
["ʌ", "V", "V", "open-mid back unrounded vowel"],
148+
["ʍ", "W", "W", "voiceless labial-velar fricative"],
149+
["χ", "X", "X", "voiceless uvular fricative"],
150+
["ʏ", "Y", "Y", "near-close front rounded vowel"],
151+
["ʒ", "Z", "Z", "voiced postalveolar fricative"],
152+
["ʋ", "P", "P", "labiodental approximant"],
153+
["͡", "_", ")", "affricate tie bar"],
154+
];
155+
const wiki = raWiki.map(([ipa, sampa, csx, name])=>({ipa, sampa, csx, name}));
156+
const bySampa = Object.fromEntries(wiki.map(e=>[e.sampa, e]));
157+
const sampaMaxLength = wiki.map(({sampa})=>sampa.length).reduce((a,b)=>Math.max(a,b));
158+
const sampa2ipa = (sampa)=>{
159+
const out = [];
160+
let i = 0;
161+
while(i < sampa.length){
162+
let n;
163+
for(n=sampaMaxLength; n>=1; n--) if(bySampa[sampa.slice(i, i+n)]) break;
164+
let ipa = bySampa[sampa.slice(i, i+n)]?.ipa;
165+
if(!ipa) ipa = sampa[i], n = 1;
166+
out.push(ipa);
167+
i += n;
168+
}
169+
return out.join('');
170+
};
171+
172+
const easyScheme = `
173+
|=,
174+
p, b, t, d, k, g, t!=tʰ, d!=dʰ, k?=q, g?=ɢ, ?=ʔ,
175+
m, n, ~n=ñ=ɲ, -ng-=ŋ,
176+
l, L=ʎ, l?=l̴,
177+
r=ɾ, rh=ɹ, R=r, R?=ʀ,
178+
s, z, sh=ʃ, zh=ʒ, f, v, th=θ, dh=ð,
179+
s!=s̺, z!=z̺, xh=ç, Jh=jh=ʝ,
180+
h, x, gh=ɣ, X=χ, r?=ʁ, h?=ħ, h,
181+
ts=t͡s, dz=d͡z, ch=tsh=t͡ʃ, J=dzh=d͡ʒ, dr=d͡ɹ,
182+
j=i*=j, w=u*=w, y*=ɥ, H?=ʕ,
183+
a, e, i, o, u, @=ə,
184+
y=-iu-=ü=y, @@=-oe-=ö=ø,
185+
E=-ea-=è=ɛ, I=ɪ, O=oh=ɔ, U=uh=ʊ,
186+
A=ʌ, a?=ɑ, o?=ɒ, -ae-=æ, 3=ɜ, Y=ʏ,
187+
M=ı=ɯ, -oea-=œ,
188+
-an-=-a?n-=ɑ̃, -ain-=ɛ̃, -on-=ɔ̃, -un-=œ̃,
189+
@r=ɚ, 3r=ɝ,
190+
`.replace(/\s+/sg, ' ');
191+
192+
const easy2ipaDict = {};
193+
const ipa2easyDict = {};
194+
for(let s of easyScheme.split(',')) if(s.trim().length){
195+
let values = s.trim().split('=');
196+
const last = values[values.length-1];
197+
ipa2easyDict[last] = values[0];
198+
for(let x of values) easy2ipaDict[x] = last;
199+
}
200+
const caphMaxLength = Object.keys(easy2ipaDict).map((k)=>k.length).reduce((a,b)=>Math.max(a,b));
201+
const ipaMaxLength = Object.keys(ipa2easyDict).map((k)=>k.length).reduce((a,b)=>Math.max(a,b));
202+
const easy2ipa = (easy)=>{
203+
const out = [];
204+
let i = 0;
205+
while(i < easy.length){
206+
let n;
207+
for(n=caphMaxLength; n>=1; n--) if(easy2ipaDict[easy.slice(i, i+n)]) break;
208+
let ipa = easy2ipaDict[easy.slice(i, i+n)];
209+
if(!ipa) ipa = easy[i], n = 1;
210+
out.push(ipa);
211+
i += n;
212+
}
213+
return out.join("");
214+
}
215+
const ipa2easy = (ipa)=>{
216+
const out = [];
217+
let i = 0;
218+
while(i < ipa.length){
219+
let n;
220+
for(n=ipaMaxLength; n>=1; n--) if(ipa2easyDict[ipa.slice(i, i+n)]) break;
221+
let easy = ipa2easyDict[ipa.slice(i, i+n)];
222+
if(!easy) easy = ipa[i], n = 1;
223+
else if(!n) n=1;
224+
out.push(easy);
225+
i += n;
226+
}
227+
return out.join("");
228+
}
229+
return {wiki, sampa2ipa, easy2ipa, ipa2easy, easy2ipaDict, ipa2easyDict};
230+
})();
231+
232+
233+
caph.injectStyle(`
234+
.font-phonetics{ font-family: "Noto Serif", serif; }
235+
`);
236+
caph.defineFileComponent((()=>{
237+
const {sampa2ipa, easy2ipa} = caph.libraries.phonetics;
238+
return ({sampa, easy, children})=>{
239+
if(children) console.warn('unexpected children in phonetics component');
240+
const ipa = easy?easy2ipa(easy): sampa2ipa(sampa);
241+
return caph.parse`<code class="font-phonetics">${ipa}</code>`;
242+
}
243+
})());

dist/font-cmu-serif.css

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/font-katex.css

Lines changed: 240 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/font-lmroman.css

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/font-lmsans.css

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)