Skip to content

Commit

Permalink
Version
Browse files Browse the repository at this point in the history
  • Loading branch information
mnater committed Oct 2, 2018
2 parents 27ba4e7 + c6a4b8f commit 5160064
Show file tree
Hide file tree
Showing 13 changed files with 572 additions and 57 deletions.
125 changes: 84 additions & 41 deletions Hyphenopoly.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @license Hyphenopoly 2.4.0 - client side hyphenation for webbrowsers
* @license Hyphenopoly 2.5.0 - client side hyphenation for webbrowsers
* ©2018 Mathias Nater, Zürich (mathiasnater at gmail dot com)
* https://github.com/mnater/Hyphenopoly
*
Expand Down Expand Up @@ -428,23 +428,18 @@
}

/**
* Hyphenate text in element
* @param {string} lang The language of the element
* @param {Object} elo The element-object
* @returns {undefined}
* Hyphenate an entitiy (text string or Element-Object)
* @param {string} lang - the language of the string
* @param {string} cn - the class of settings
* @param {string} entity - the entity to be hyphenated
* @returns {string | null} hyphenated string according to setting of cn
*/
function hyphenateElement(lang, elo) {
const el = elo.element;
function hyphenate(lang, cn, entity) {
const lo = H.languages[lang];
const cn = elo.class;
const classSettings = C[cn];
const minWordLength = classSettings.minWordLength;
const normalize = C.normalize &&
Boolean(String.prototype.normalize);
H.events.dispatch("beforeElementHyphenation", {
"el": el,
"lang": lang
});
const poolKey = lang + "-" + cn;
const wordHyphenator = (wordHyphenatorPool[poolKey])
? wordHyphenatorPool[poolKey]
Expand All @@ -453,37 +448,72 @@
? orphanControllerPool[cn]
: createOrphanController(cn);
const re = lo.genRegExps[cn];
let i = 0;
let n = el.childNodes[i];
while (n) {
if (
n.nodeType === 3 &&
n.data.length >= minWordLength
) {
let tn = null;
if (normalize) {
tn = n.data.normalize("NFC").replace(re, wordHyphenator);
} else {
tn = n.data.replace(re, wordHyphenator);
}
if (classSettings.orphanControl !== 1) {
tn = tn.replace(
/(\u0020*)(\S+)(\s*)$/,
orphanController
);

/**
* Hyphenate text according to setting in cn
* @param {string} text - the strint to be hyphenated
* @returns {string} hyphenated string according to setting of cn
*/
function hyphenateText(text) {
let tn = null;
if (normalize) {
tn = text.normalize("NFC").replace(re, wordHyphenator);
} else {
tn = text.replace(re, wordHyphenator);
}
if (classSettings.orphanControl !== 1) {
tn = tn.replace(
/(\u0020*)(\S+)(\s*)$/,
orphanController
);
}
return tn;
}

/**
* Hyphenate element according to setting in cn
* @param {object} el - the HTMLElement to be hyphenated
* @returns {undefined}
*/
function hyphenateElement(el) {
H.events.dispatch("beforeElementHyphenation", {
"el": el,
"lang": lang
});
let i = 0;
let n = el.childNodes[i];
while (n) {
if (
n.nodeType === 3 &&
n.data.length >= minWordLength
) {
n.data = hyphenateText(n.data);
}
n.data = tn;
i += 1;
n = el.childNodes[i];
}
i += 1;
n = el.childNodes[i];
elements.counter[0] -= 1;
H.events.dispatch("afterElementHyphenation", {
"el": el,
"lang": lang
});
}
elements.counter[0] -= 1;
H.events.dispatch("afterElementHyphenation", {
"el": el,
"lang": lang
});
let r = null;
if (typeof entity === "string") {
r = hyphenateText(entity);
} else if (entity instanceof HTMLElement) {
hyphenateElement(entity);
}
return r;
}

H.createHyphenator = function createHyphenator(lang) {
return function hyphenator(entity, cn) {
cn = cn || "hyphenate";
return hyphenate(lang, cn, entity);
};
};

/**
* Hyphenate all elements with a given language
* @param {string} lang The language
Expand All @@ -493,7 +523,7 @@
function hyphenateLangElements(lang, elArr) {
if (elArr) {
elArr.forEach(function eachElem(elo) {
hyphenateElement(lang, elo);
hyphenate(lang, elo.class, elo.element);
});
} else {
H.events.dispatch("error", {"msg": "engine for language '" + lang + "' loaded, but no elements found."});
Expand Down Expand Up @@ -607,6 +637,15 @@
classSettings.rightmin
);
}

/*
* Find words with characters from `alphabet` and
* `Zero Width Non-Joiner` and `-` with a min length.
*
* This regexp is not perfect. It also finds parts of words
* that follow a character that is not in the `alphabet`.
* Word delimiters are not taken in account.
*/
lo.genRegExps[cn] = new RegExp("[\\w" + alphabet + String.fromCharCode(8204) + "-]{" + classSettings.minWordLength + ",}", "gi");
});
lo.engineReady = true;
Expand Down Expand Up @@ -787,12 +826,16 @@
const defRightmin = baseData.rightmin;
const hyphenatedWordStore = (new Uint16Array(heapBuffer)).subarray(
hyphenatedWordOffset >> 1,
(hyphenatedWordOffset >> 1) + 64
(hyphenatedWordOffset >> 1) + 128
);
/* eslint-enable no-bitwise */
return function hyphenate(word, hyphenchar, leftmin, rightmin) {
return function enclHyphenate(word, hyphenchar, leftmin, rightmin) {
let i = 0;
const wordLength = word.length;
if (wordLength > 61) {
H.events.dispatch("error", {"msg": "found word longer than 61 characters"});
return word;
}
leftmin = leftmin || defLeftmin;
rightmin = rightmin || defRightmin;
wordStore[0] = wordLength + 2;
Expand Down
54 changes: 53 additions & 1 deletion Hyphenopoly_Loader.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @license Hyphenopoly_Loader 2.4.0 - client side hyphenation
* @license Hyphenopoly_Loader 2.5.0 - client side hyphenation
* ©2018 Mathias Nater, Zürich (mathiasnater at gmail dot com)
* https://github.com/mnater/Hyphenopoly
*
Expand Down Expand Up @@ -525,16 +525,67 @@
);
}

/**
* Expose the hyphenate-function of a specific language to
* Hyphenopoly.hyphenators.<language>
*
* Hyphenopoly.hyphenators.<language> is a Promise that fullfills
* to hyphenate(lang, cn, entity) as soon as the ressources are loaded
* and the engine is ready.
* If Promises aren't supported (e.g. IE11) a error message is produced.
*
* @param {string} lang - the language
* @returns {undefined}
*/
function exposeHyphenateFunction(lang) {
if (!H.hyphenators) {
H.hyphenators = {};
}
if (!H.hyphenators[lang]) {
if (window.Promise) {
H.hyphenators[lang] = new Promise(function pro(rs, rj) {
H.events.addListener("engineReady", function handler(e) {
if (e.msg === lang) {
rs(H.createHyphenator(e.msg));
}
}, true);
H.events.addListener("error", function handler(e) {
e.preventDefault();
if (e.key === lang || e.key === "hyphenEngine") {
rj(e.msg);
}
}, true);
});
} else {
H.hyphenators[lang] = {

/**
* Fires an error message, if then is called
* @returns {undefined}
*/
"then": function () {
H.events.dispatch(
"error",
{"msg": "Promises not supported in this engine. Use a polyfill (e.g. https://github.com/taylorhakes/promise-polyfill)!"}
);
}
};
}
}
}

Object.keys(H.require).forEach(function doReqLangs(lang) {
if (H.require[lang] === "FORCEHYPHENOPOLY") {
H.clientFeat.polyfill = true;
H.clientFeat.langs[lang] = "H9Y";
loadRessources(lang);
exposeHyphenateFunction(lang);
} else if (
H.clientFeat.langs[lang] &&
H.clientFeat.langs[lang] === "H9Y"
) {
loadRessources(lang);
exposeHyphenateFunction(lang);
} else {
tester.createTest(lang);
}
Expand All @@ -550,6 +601,7 @@
H.clientFeat.polyfill = true;
H.clientFeat.langs[lang] = "H9Y";
loadRessources(lang);
exposeHyphenateFunction(lang);
}
}
});
Expand Down
4 changes: 4 additions & 0 deletions example.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// For RunKit:
const hyphenopoly = require("hyphenopoly");

// For local node:
// const hyphenopoly = require("./hyphenopoly.module.js");

const hyphenator = hyphenopoly.config({
"require": ["de", "en-us"],
"hyphen": "•",
Expand Down
2 changes: 1 addition & 1 deletion hyphenEngine.asm.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @license hyphenEngine.asm.js 2.4.0 - client side hyphenation for webbrowsers
* @license hyphenEngine.asm.js 2.5.0 - client side hyphenation for webbrowsers
* ©2018 Mathias Nater, Zürich (mathiasnater at gmail dot com)
* https://github.com/mnater/Hyphenopoly
*
Expand Down
57 changes: 50 additions & 7 deletions hyphenopoly.module.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @license Hyphenopoly.module.js 2.4.0 - hyphenation for node
* @license Hyphenopoly.module.js 2.5.0 - hyphenation for node
* ©2018 Mathias Nater, Zürich (mathiasnater at gmail dot com)
* https://github.com/mnater/Hyphenopoly
*
Expand All @@ -12,12 +12,12 @@
"use strict";

const fs = require("fs");
const ut = require("util");

const {StringDecoder} = require("string_decoder");
const decode = (function makeDecoder() {
const utf16ledecoder = new (ut.TextDecoder)("utf-16le");
const utf16ledecoder = new StringDecoder("utf-16le");
return function dec(ui16) {
return utf16ledecoder.decode(ui16);
return utf16ledecoder.write(ui16);
};
}());

Expand Down Expand Up @@ -57,12 +57,48 @@ function setProp(val, props) {
const H = empty();
H.binaries = empty();

/**
* Read a file and call callback
* Use "fs" (node) or "http" (browser)
* @param {string} file - the filename
* @param {function} cb - callback function
* @returns {undefined}
*/
function readFile(file, cb) {
fs.readFile(file, cb);
}

/**
* Before using browserify comment-out or delete the readFile-function above
* and un-comment the following function.
* Also change `const fs = require("fs");` to `const http = require("http");`
* at the top of the file
*/

/**
* Browserify-compatible readFile:
* function readFile(file, cb) {
* const rawData = [];
* http.get(file, function c(res) {
* res.on("data", function onData(chunk) {
* rawData.push(chunk);
* });
* res.on("end", function onEnd() {
* cb(null, Buffer.concat(rawData));
* });
* res.on("error", function onErr(err) {
* cb(err, rawData);
* });
* });
* }
*/

/**
* Read a wasm file, dispatch "engineLoaded" on success
* @returns {undefined}
*/
function loadWasm() {
fs.readFile(
readFile(
`${H.c.paths.maindir}hyphenEngine.wasm`,
function cb(err, data) {
if (err) {
Expand All @@ -84,7 +120,7 @@ function loadWasm() {
* @returns {undefined}
*/
function loadHpb(lang) {
fs.readFile(
readFile(
`${H.c.paths.patterndir}${lang}.hpb`,
function cb(err, data) {
if (err) {
Expand Down Expand Up @@ -284,7 +320,7 @@ function encloseHyphenateFunction(baseData, hyphenateFunc) {
const defRightmin = baseData.rightmin;
const hyphenatedWordStore = (new Uint16Array(heapBuffer)).subarray(
hyphenatedWordOffset >> 1,
(hyphenatedWordOffset >> 1) + 64
(hyphenatedWordOffset >> 1) + 128
);
/* eslint-enable no-bitwise */

Expand All @@ -301,6 +337,13 @@ function encloseHyphenateFunction(baseData, hyphenateFunc) {
return function hyphenate(word, hyphenchar, leftmin, rightmin) {
let i = 0;
const wordLength = word.length;
if (wordLength > 61) {
H.events.dispatch(
"error",
{"msg": "found word longer than 61 characters"}
);
return word;
}
leftmin = leftmin || defLeftmin;
rightmin = rightmin || defRightmin;
wordStore[0] = wordLength + 2;
Expand Down
Loading

0 comments on commit 5160064

Please sign in to comment.