Support for the FreeMonoTengwar font and ConScript encoding
[tengwarjs.git] / tengwar-annatar.js
1
2 var Alphabet = require("./alphabet");
3 var Bindings = require("./dan-smith");
4 var makeFontColumn = require("./column");
5
6 var tengwar = exports.tengwar = Bindings.tengwar;
7 var tehtar = exports.tehtar = Bindings.tehtar;
8
9 var positions = exports.positions = {
10
11 "tinco": {
12 "o": 3,
13 "w": 3,
14 "others": 2
15 },
16 "parma": {
17 "o": 3,
18 "w": 3,
19 "others": 2
20 },
21 "calma": {
22 "o": 3,
23 "w": 3,
24 "u": 3,
25 "o-below": 1,
26 "others": 2
27 },
28 "quesse": {
29 "o": 3,
30 "w": 3,
31 "o-below": 1,
32 "others": 2
33 },
34
35 "ando": {
36 "wide": true,
37 "e": 1,
38 "o": 2,
39 "ó": 1,
40 "ú": 1,
41 "others": 0
42 },
43 "umbar": {
44 "wide": true,
45 "e": 1,
46 "o": 2,
47 "ó": 1,
48 "ú": 1,
49 "others": 0
50 },
51 "anga": {
52 "wide": true,
53 "e": 1,
54 "ó": 1,
55 "ú": 1,
56 "others": 0
57 },
58 "ungwe": {
59 "wide": true,
60 "e": 1,
61 "o": 1,
62 "ó": 1,
63 "ú": 1,
64 "others": 0
65 },
66
67 "thule": {
68 "others": 3
69 },
70 "formen": 3,
71 "harma": {
72 "e": 0,
73 "o": 3,
74 "u": 7,
75 "ó": 2,
76 "ú": 2,
77 "w": 0,
78 "others": 1
79 },
80 "hwesta": {
81 "e": 0,
82 "o": 3,
83 "u": 7,
84 "w": 0,
85 "others": 1
86 },
87
88 "anto": {
89 "wide": true,
90 "ó": 1,
91 "ú": 1,
92 "others": 0
93 },
94 "ampa": {
95 "wide": true,
96 "ó": 1,
97 "ú": 1,
98 "others": 0
99 },
100 "anca": {
101 "wide": true,
102 "u": 7,
103 "ó": 1,
104 "ú": 1,
105 "others": 0
106 },
107 "unque": {
108 "wide": true,
109 "u": 7,
110 "others": 0
111 },
112
113 "numen": {
114 "wide": true,
115 "ó": 1,
116 "ú": 1,
117 "others": 0
118 },
119 "malta": {
120 "wide": true,
121 "ó": 1,
122 "ú": 1,
123 "others": 0
124 },
125 "noldo": {
126 "wide": true,
127 "ó": 1,
128 "ú": 1,
129 "others": 0
130 },
131 "nwalme": {
132 "wide": true,
133 "ó": 1,
134 "ú": 1,
135 "others": 0
136 },
137
138 "ore": {
139 "e": 3,
140 "o": 3,
141 "u": 3,
142 "ó": 3,
143 "ú": 3,
144 "others": 1
145 },
146 "vala": {
147 "e": 3,
148 "o": 3,
149 "u": 3,
150 "ó": 3,
151 "ú": 3,
152 "others": 1
153 },
154 "anna": {
155 "e": 3,
156 "o": 3,
157 "u": 3,
158 "ó": 2,
159 "ú": 2,
160 "others": 1
161 },
162 "wilya": {
163 "e": 3,
164 "o": 3,
165 "u": 3,
166 "ó": 3,
167 "ú": 3,
168 "others": 1
169 },
170
171 "romen": {
172 "e": 3,
173 "o": 3,
174 "u": 3,
175 "ó": 2,
176 "ú": 2,
177 "y": 3,
178 "o-below": null,
179 "i-below": 3,
180 "others": 1
181 },
182 "arda": {
183 "a": 1,
184 "e": 3,
185 "i": 1,
186 "o": 3,
187 "u": 3,
188 "í": 1,
189 "ó": 2,
190 "ú": 2,
191 "y": 3,
192 "o-below": null,
193 "i-below": 3,
194 "others": 0
195 },
196 "lambe": {
197 "wide": true,
198 "e": 1,
199 "y": 4,
200 "ó": 1,
201 "ú": 1,
202 "o-below": null,
203 "i-below": 4,
204 "others": 0
205 },
206 "alda": {
207 "wide": true,
208 "o-below": null,
209 "others": 1
210 },
211
212 "silme": {
213 "y": 3,
214 "o-below": 2,
215 "i-below": 2,
216 "others": null
217 },
218 "silme-nuquerna": {
219 "e": 3,
220 "o": 3,
221 "u": 3,
222 "ó": 3,
223 "ú": 3,
224 "y": null,
225 "o-below": null,
226 "i-below": null,
227 "others": 1
228 },
229 "esse": {
230 "y": null,
231 "others": null
232 },
233 "esse-nuquerna": {
234 "e": 3,
235 "o": 3,
236 "u": 3,
237 "ó": 3,
238 "ú": 3,
239 "others": 1
240 },
241
242 "hyarmen": 3,
243 "hwesta-sindarinwa": {
244 "o": 2,
245 "u": 2,
246 "ó": 1,
247 "ú": 2,
248 "others": 0
249 },
250 "yanta": {
251 "e": 3,
252 "o": 3,
253 "u": 3,
254 "ó": 2,
255 "ú": 2,
256 "others": 1
257 },
258 "ure": {
259 "e": 3,
260 "o": 3,
261 "u": 3,
262 "ó": 3,
263 "ú": 3,
264 "others": 1
265 },
266
267 // should not occur:
268 "halla": {
269 "i-below": 3,
270 "others": null
271 },
272 "short-carrier": 3,
273 "long-carrier": {
274 "y": null,
275 "o-below": null,
276 "i-below": null,
277 "others": 3
278 },
279 "round-carrier": 3,
280
281 "tinco-extended": 3,
282 "parma-extended": 3,
283 "calma-extended": {
284 "o": 3,
285 "u": 7,
286 "ó": 2,
287 "ú": 2,
288 "others": 1
289 },
290 "quesse-extended": {
291 "o": 0,
292 "u": 7,
293 "others": 1
294 },
295
296 "ando-extended": {
297 "wide": true,
298 "e": 1,
299 "o": 2,
300 "ó": 1,
301 "ú": 1,
302 "others": 0
303 },
304 "umbar-extended": {
305 "wide": true,
306 "e": 1,
307 "o": 2,
308 "ó": 1,
309 "ú": 1,
310 "others": 0
311 },
312 "anga-extended": {
313 "wide": true,
314 "e": 1,
315 "ó": 1,
316 "ú": 1,
317 "others": 0
318 },
319 "ungwe-extended": {
320 "wide": true,
321 "e": 1,
322 "o": 1,
323 "ó": 1,
324 "ú": 1,
325 "others": 0
326 }
327 };
328
329 exports.transcribe = transcribe;
330 function transcribe(sections, options) {
331 options = options || {};
332 var block = options.block || false;
333 var beginParagraph = block ? "<p>" : "";
334 var delimitParagraph = "<br>";
335 var endParagraph = block ? "</p>" : "";
336 return sections.map(function (section) {
337 return section.map(function (paragraph) {
338 return beginParagraph + paragraph.map(function (line) {
339 return line.map(function (word) {
340 return word.map(function (column) {
341 return transcribeColumn(column, options);
342 }).join("");
343 }).join(" ");;
344 }).join(delimitParagraph + "\n") + endParagraph;
345 }).join("\n\n");
346 }).join("\n\n\n");
347 }
348
349 exports.transcribeColumn = transcribeColumn;
350 function transcribeColumn(column, options) {
351 options = options || {};
352 var plain = options.plain || false;
353 var tengwa = column.tengwa || "anna";
354 var tehtar = [];
355 if (column.above) tehtar.push(column.above);
356 if (column.below) tehtar.push(column.below);
357 if (column.tildeBelow) tehtar.push("tilde-below");
358 if (column.tildeAbove) tehtar.push("tilde-above");
359 if (column.following) tehtar.push(column.following);
360 var html = tengwar[tengwa] + tehtar.map(function (tehta) {
361 return tehtaForTengwa(tengwa, tehta);
362 }).join("");
363 if (column.errors && !plain) {
364 html = "<abbr class=\"error\" title=\"" + column.errors.join("\n").replace(/"/g, "&quot;") + "\">" + html + "</abbr>";
365 }
366 return html;
367 }
368
369 exports.tehtaForTengwa = tehtaForTengwa;
370 function tehtaForTengwa(tengwa, tehta) {
371 var tehtaKey = tehtaKeyForTengwa(tengwa, tehta);
372 if (tehtaKey == null)
373 return null;
374 return (
375 tehtar[tehta][tengwa] ||
376 tehtar[tehta][tehtaKey] ||
377 ""
378 );
379 }
380
381 function tehtaKeyForTengwa(tengwa, tehta) {
382 if (!tehtar[tehta])
383 return null;
384 if (tehtar[tehta].special)
385 return tehtar[tehta][tengwa] || null;
386 if (Alphabet.barsAndTildes.indexOf(tehta) !== -1) {
387 if (tengwa === "lambe" || tengwa === "alda" && tehtar[tehta].length >= 2)
388 return 2;
389 return positions[tengwa].wide ? 0 : 1;
390 }
391 if (positions[tengwa] == null)
392 return null;
393 if (positions[tengwa][tehta] === null)
394 return null;
395 if (positions[tengwa][tehta] != null)
396 return positions[tengwa][tehta];
397 if (positions[tengwa].others != null)
398 return positions[tengwa].others;
399 return positions[tengwa];
400 }
401
402 exports.makeColumn = makeColumn;
403 function makeColumn(tengwa, tengwarFrom) {
404 return makeFontColumn(exports, tengwa, tengwarFrom);
405 }
406