Structured content data (#1930)
* Add support for structured-content data attributes * Assign dataset properties * Don't remove data-sc attributes * Use helper functions * Update test data
This commit is contained in:
parent
eb457caea9
commit
f68ad1f843
@ -28,6 +28,9 @@
|
||||
"tag": {
|
||||
"type": "string",
|
||||
"enum": ["br"]
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/definitions/structuredContentData"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -45,6 +48,9 @@
|
||||
},
|
||||
"content": {
|
||||
"$ref": "#/definitions/structuredContent"
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/definitions/structuredContentData"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -63,6 +69,9 @@
|
||||
"content": {
|
||||
"$ref": "#/definitions/structuredContent"
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/definitions/structuredContentData"
|
||||
},
|
||||
"colSpan": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
@ -91,6 +100,9 @@
|
||||
"content": {
|
||||
"$ref": "#/definitions/structuredContent"
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/definitions/structuredContentData"
|
||||
},
|
||||
"style": {
|
||||
"$ref": "#/definitions/structuredContentStyle"
|
||||
}
|
||||
@ -109,6 +121,9 @@
|
||||
"type": "string",
|
||||
"const": "img"
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/definitions/structuredContentData"
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "Path to the image file in the archive."
|
||||
@ -175,6 +190,13 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"structuredContentData": {
|
||||
"type": "object",
|
||||
"description": "Generic data attributes that should be added to the element.",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"structuredContentStyle": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
@ -169,6 +169,16 @@ class StructuredContentGenerator {
|
||||
return this._document.createDocumentFragment();
|
||||
}
|
||||
|
||||
_setElementDataset(element, data) {
|
||||
for (let [key, value] of Object.entries(data)) {
|
||||
if (key.length > 0) {
|
||||
key = `${key[0].toUpperCase()}${key.substring(1)}`;
|
||||
}
|
||||
key = `sc${key}`;
|
||||
element.dataset[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
_setImageData(node, image, imageBackground, url, unloaded) {
|
||||
if (url !== null) {
|
||||
image.src = url;
|
||||
@ -192,6 +202,8 @@ class StructuredContentGenerator {
|
||||
|
||||
_createStructuredContentElement(tag, content, dictionary, type, hasChildren, hasStyle) {
|
||||
const node = this._createElement(tag, `gloss-sc-${tag}`);
|
||||
const {data} = content;
|
||||
if (typeof data === 'object' && data !== null) { this._setElementDataset(node, data); }
|
||||
switch (type) {
|
||||
case 'table-cell':
|
||||
{
|
||||
|
@ -38,6 +38,7 @@ class AnkiTemplateRenderer {
|
||||
constructor() {
|
||||
this._structuredContentStyleApplier = new CssStyleApplier('/data/structured-content-style.json');
|
||||
this._pronunciationStyleApplier = new CssStyleApplier('/data/pronunciation-style.json');
|
||||
this._structuredContentDatasetKeyIgnorePattern = /^sc([^a-z]|$)/;
|
||||
this._japaneseUtil = new JapaneseUtil(null);
|
||||
this._templateRenderer = new TemplateRenderer();
|
||||
this._ankiNoteDataCreator = new AnkiNoteDataCreator(this._japaneseUtil);
|
||||
@ -462,16 +463,24 @@ class AnkiTemplateRenderer {
|
||||
return element;
|
||||
}
|
||||
|
||||
_getHtml(node, styleApplier) {
|
||||
_getStructuredContentHtml(node) {
|
||||
return this._getHtml(node, this._structuredContentStyleApplier, this._structuredContentDatasetKeyIgnorePattern);
|
||||
}
|
||||
|
||||
_getPronunciationHtml(node) {
|
||||
return this._getHtml(node, this._pronunciationStyleApplier, null);
|
||||
}
|
||||
|
||||
_getHtml(node, styleApplier, datasetKeyIgnorePattern) {
|
||||
const container = this._getTemporaryElement();
|
||||
container.appendChild(node);
|
||||
this._normalizeHtml(container, styleApplier);
|
||||
this._normalizeHtml(container, styleApplier, datasetKeyIgnorePattern);
|
||||
const result = container.innerHTML;
|
||||
container.textContent = '';
|
||||
return result;
|
||||
}
|
||||
|
||||
_normalizeHtml(root, styleApplier) {
|
||||
_normalizeHtml(root, styleApplier, datasetKeyIgnorePattern) {
|
||||
const {ELEMENT_NODE, TEXT_NODE} = Node;
|
||||
const treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);
|
||||
const elements = [];
|
||||
@ -492,6 +501,7 @@ class AnkiTemplateRenderer {
|
||||
for (const element of elements) {
|
||||
const {dataset} = element;
|
||||
for (const key of Object.keys(dataset)) {
|
||||
if (datasetKeyIgnorePattern !== null && datasetKeyIgnorePattern.test(key)) { continue; }
|
||||
delete dataset[key];
|
||||
}
|
||||
}
|
||||
@ -541,13 +551,13 @@ class AnkiTemplateRenderer {
|
||||
_formatGlossaryImage(content, dictionary, data) {
|
||||
const structuredContentGenerator = this._createStructuredContentGenerator(data);
|
||||
const node = structuredContentGenerator.createDefinitionImage(content, dictionary);
|
||||
return this._getHtml(node, this._structuredContentStyleApplier);
|
||||
return this._getStructuredContentHtml(node);
|
||||
}
|
||||
|
||||
_formatStructuredContent(content, dictionary, data) {
|
||||
const structuredContentGenerator = this._createStructuredContentGenerator(data);
|
||||
const node = structuredContentGenerator.createStructuredContent(content.content, dictionary);
|
||||
return node !== null ? this._getHtml(node, this._structuredContentStyleApplier) : '';
|
||||
return node !== null ? this._getStructuredContentHtml(node) : '';
|
||||
}
|
||||
|
||||
_hasMedia(context, ...args) {
|
||||
@ -575,20 +585,11 @@ class AnkiTemplateRenderer {
|
||||
|
||||
switch (format) {
|
||||
case 'text':
|
||||
return this._getHtml(
|
||||
this._pronunciationGenerator.createPronunciationText(morae, downstepPosition, nasalPositions, devoicePositions),
|
||||
this._pronunciationStyleApplier
|
||||
);
|
||||
return this._getPronunciationHtml(this._pronunciationGenerator.createPronunciationText(morae, downstepPosition, nasalPositions, devoicePositions));
|
||||
case 'graph':
|
||||
return this._getHtml(
|
||||
this._pronunciationGenerator.createPronunciationGraph(morae, downstepPosition),
|
||||
this._pronunciationStyleApplier
|
||||
);
|
||||
return this._getPronunciationHtml(this._pronunciationGenerator.createPronunciationGraph(morae, downstepPosition));
|
||||
case 'position':
|
||||
return this._getHtml(
|
||||
this._pronunciationGenerator.createPronunciationDownstepPosition(downstepPosition),
|
||||
this._pronunciationStyleApplier
|
||||
);
|
||||
return this._getPronunciationHtml(this._pronunciationGenerator.createPronunciationDownstepPosition(downstepPosition));
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
@ -164,6 +164,21 @@
|
||||
]
|
||||
},
|
||||
"margin"
|
||||
]},
|
||||
{"type": "structured-content", "content": [
|
||||
"text 1 ",
|
||||
{
|
||||
"tag": "span",
|
||||
"data": {
|
||||
"": "empty",
|
||||
"a": "b",
|
||||
"c": "d"
|
||||
},
|
||||
"content": [
|
||||
"text 2"
|
||||
]
|
||||
},
|
||||
" text 3"
|
||||
]}
|
||||
],
|
||||
100, "P E1"
|
||||
|
Loading…
Reference in New Issue
Block a user