aboutsummaryrefslogtreecommitdiff
path: root/ext/js/display/sandbox/structured-content-generator.js
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2022-05-14 18:12:57 -0400
committerGitHub <noreply@github.com>2022-05-14 18:12:57 -0400
commit5dcc2315d242bcec29cc478618d448c941f73ab1 (patch)
tree9d36e666cc71bb1c1a89c725eaa9fdaa5c938626 /ext/js/display/sandbox/structured-content-generator.js
parent6a74746113c724e750620d10b58ad6bac94060c9 (diff)
Structured content auto language (#2131)
* Pass JapaneseUtil instance to StructuredContentGenerator * Move body of createStructuredContent to an internal function * Create _createStructuredContentGenericElement * Wrap structured content in a <span> * Change _createStructuredContent to _appendStructuredContent * Add public appendStructuredContent function * Add missing return * Remove unused _createDocumentFragment * Automatically assign lang=ja for content with Japanese characters without an explicit language * Add test
Diffstat (limited to 'ext/js/display/sandbox/structured-content-generator.js')
-rw-r--r--ext/js/display/sandbox/structured-content-generator.js141
1 files changed, 82 insertions, 59 deletions
diff --git a/ext/js/display/sandbox/structured-content-generator.js b/ext/js/display/sandbox/structured-content-generator.js
index 6102cfdd..5b11965a 100644
--- a/ext/js/display/sandbox/structured-content-generator.js
+++ b/ext/js/display/sandbox/structured-content-generator.js
@@ -16,56 +16,21 @@
*/
class StructuredContentGenerator {
- constructor(contentManager, document) {
+ constructor(contentManager, japaneseUtil, document) {
this._contentManager = contentManager;
+ this._japaneseUtil = japaneseUtil;
this._document = document;
}
+ appendStructuredContent(node, content, dictionary) {
+ node.classList.add('structured-content');
+ this._appendStructuredContent(node, content, dictionary, null);
+ }
+
createStructuredContent(content, dictionary) {
- if (typeof content === 'string') {
- return this._createTextNode(content);
- }
- if (!(typeof content === 'object' && content !== null)) {
- return null;
- }
- if (Array.isArray(content)) {
- const fragment = this._createDocumentFragment();
- for (const item of content) {
- const child = this.createStructuredContent(item, dictionary);
- if (child !== null) { fragment.appendChild(child); }
- }
- return fragment;
- }
- const {tag} = content;
- switch (tag) {
- case 'br':
- return this._createStructuredContentElement(tag, content, dictionary, 'simple', false, false);
- case 'ruby':
- case 'rt':
- case 'rp':
- return this._createStructuredContentElement(tag, content, dictionary, 'simple', true, false);
- case 'table':
- return this._createStructuredContentTableElement(tag, content, dictionary);
- case 'thead':
- case 'tbody':
- case 'tfoot':
- case 'tr':
- return this._createStructuredContentElement(tag, content, dictionary, 'table', true, false);
- case 'th':
- case 'td':
- return this._createStructuredContentElement(tag, content, dictionary, 'table-cell', true, true);
- case 'div':
- case 'span':
- case 'ol':
- case 'ul':
- case 'li':
- return this._createStructuredContentElement(tag, content, dictionary, 'simple', true, true);
- case 'img':
- return this.createDefinitionImage(content, dictionary);
- case 'a':
- return this._createLinkElement(content, dictionary);
- }
- return null;
+ const node = this._createElement('span', 'structured-content');
+ this._appendStructuredContent(node, content, dictionary, null);
+ return node;
}
createDefinitionImage(data, dictionary) {
@@ -160,6 +125,31 @@ class StructuredContentGenerator {
// Private
+ _appendStructuredContent(container, content, dictionary, language) {
+ if (typeof content === 'string') {
+ if (content.length > 0) {
+ container.appendChild(this._createTextNode(content));
+ if (language === null && this._japaneseUtil.isStringPartiallyJapanese(content)) {
+ container.lang = 'ja';
+ }
+ }
+ return;
+ }
+ if (!(typeof content === 'object' && content !== null)) {
+ return;
+ }
+ if (Array.isArray(content)) {
+ for (const item of content) {
+ this._appendStructuredContent(container, item, dictionary, language);
+ }
+ return;
+ }
+ const node = this._createStructuredContentGenericElement(content, dictionary, language);
+ if (node !== null) {
+ container.appendChild(node);
+ }
+ }
+
_createElement(tagName, className) {
const node = this._document.createElement(tagName);
node.className = className;
@@ -170,10 +160,6 @@ class StructuredContentGenerator {
return this._document.createTextNode(data);
}
- _createDocumentFragment() {
- return this._document.createDocumentFragment();
- }
-
_setElementDataset(element, data) {
for (let [key, value] of Object.entries(data)) {
if (key.length > 0) {
@@ -198,18 +184,54 @@ class StructuredContentGenerator {
}
}
- _createStructuredContentTableElement(tag, content, dictionary) {
+ _createStructuredContentGenericElement(content, dictionary, language) {
+ const {tag} = content;
+ switch (tag) {
+ case 'br':
+ return this._createStructuredContentElement(tag, content, dictionary, language, 'simple', false, false);
+ case 'ruby':
+ case 'rt':
+ case 'rp':
+ return this._createStructuredContentElement(tag, content, dictionary, language, 'simple', true, false);
+ case 'table':
+ return this._createStructuredContentTableElement(tag, content, dictionary, language);
+ case 'thead':
+ case 'tbody':
+ case 'tfoot':
+ case 'tr':
+ return this._createStructuredContentElement(tag, content, dictionary, language, 'table', true, false);
+ case 'th':
+ case 'td':
+ return this._createStructuredContentElement(tag, content, dictionary, language, 'table-cell', true, true);
+ case 'div':
+ case 'span':
+ case 'ol':
+ case 'ul':
+ case 'li':
+ return this._createStructuredContentElement(tag, content, dictionary, language, 'simple', true, true);
+ case 'img':
+ return this.createDefinitionImage(content, dictionary);
+ case 'a':
+ return this._createLinkElement(content, dictionary, language);
+ }
+ return null;
+ }
+
+ _createStructuredContentTableElement(tag, content, dictionary, language) {
const container = this._createElement('div', 'gloss-sc-table-container');
- const table = this._createStructuredContentElement(tag, content, dictionary, 'table', true, false);
+ const table = this._createStructuredContentElement(tag, content, dictionary, language, 'table', true, false);
container.appendChild(table);
return container;
}
- _createStructuredContentElement(tag, content, dictionary, type, hasChildren, hasStyle) {
+ _createStructuredContentElement(tag, content, dictionary, language, type, hasChildren, hasStyle) {
const node = this._createElement(tag, `gloss-sc-${tag}`);
const {data, lang} = content;
if (typeof data === 'object' && data !== null) { this._setElementDataset(node, data); }
- if (typeof lang === 'string') { node.lang = lang; }
+ if (typeof lang === 'string') {
+ node.lang = lang;
+ language = lang;
+ }
switch (type) {
case 'table-cell':
{
@@ -226,8 +248,7 @@ class StructuredContentGenerator {
}
}
if (hasChildren) {
- const child = this.createStructuredContent(content.content, dictionary);
- if (child !== null) { node.appendChild(child); }
+ this._appendStructuredContent(node, content.content, dictionary, language);
}
return node;
}
@@ -262,7 +283,7 @@ class StructuredContentGenerator {
if (typeof listStyleType === 'string') { style.listStyleType = listStyleType; }
}
- _createLinkElement(content, dictionary) {
+ _createLinkElement(content, dictionary, language) {
let {href} = content;
const internal = href.startsWith('?');
if (internal) {
@@ -276,10 +297,12 @@ class StructuredContentGenerator {
node.appendChild(text);
const {lang} = content;
- if (typeof lang === 'string') { node.lang = lang; }
+ if (typeof lang === 'string') {
+ node.lang = lang;
+ language = lang;
+ }
- const child = this.createStructuredContent(content.content, dictionary);
- if (child !== null) { text.appendChild(child); }
+ this._appendStructuredContent(text, content.content, dictionary, language);
if (!internal) {
const icon = this._createElement('span', 'gloss-link-external-icon icon');