Add new structured content features: lists and the HTML lang
attribute (#2129)
* Add support for structured content lists and `list-style-type` style A full list of supported style types is documented here: https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type There's nothing in this code preventing a term bank from assigning, for example, a `list-style-type` style to a `div` element, but it doesn't seem like browsers will complain about things like that. * Add support for `lang` attribute in structured content Support added for the following node types: "ruby", "rt", "rp", "table", "thead", "tbody", "tfoot", "tr", "td", "th", "span", "div", "ol", "ul", "li", "a" I couldn't get it to work for the alt-hover text on "img" tags. Tests are included in the file "test/data/dictionaries/valid-dictionary/term_bank_1.json" * Add styles for structured content lists * Add override rules for new structured-content list styles see: https://github.com/FooSoft/yomichan/pull/2129 Co-authored-by: stephenmk <stephenmk@users.noreply.github.com>
This commit is contained in:
parent
e9843f67cb
commit
6a74746113
@ -61,3 +61,16 @@
|
|||||||
display: none;
|
display: none;
|
||||||
/* remove-property background-color vertical-align width height margin-left background-color position */
|
/* remove-property background-color vertical-align width height margin-left background-color position */
|
||||||
}
|
}
|
||||||
|
.gloss-sc-ol,
|
||||||
|
.gloss-sc-ul {
|
||||||
|
/* remove-property padding-left */
|
||||||
|
}
|
||||||
|
:root[data-glossary-layout-mode=compact] .gloss-sc-ul[data-sc-content=glossary] {
|
||||||
|
/* remove-rule */
|
||||||
|
}
|
||||||
|
:root[data-glossary-layout-mode=compact] .gloss-sc-ul[data-sc-content=glossary] .gloss-sc-li {
|
||||||
|
/* remove-rule */
|
||||||
|
}
|
||||||
|
:root[data-glossary-layout-mode=compact] .gloss-sc-ul[data-sc-content=glossary] .gloss-sc-li:not(:first-child)::before {
|
||||||
|
/* remove-rule */
|
||||||
|
}
|
||||||
|
@ -235,3 +235,21 @@
|
|||||||
padding: 0.25em;
|
padding: 0.25em;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
.gloss-sc-ol,
|
||||||
|
.gloss-sc-ul {
|
||||||
|
padding-left: var(--list-padding2);
|
||||||
|
}
|
||||||
|
:root[data-glossary-layout-mode=compact] .gloss-sc-ul[data-sc-content=glossary] {
|
||||||
|
display: inline;
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
:root[data-glossary-layout-mode=compact] .gloss-sc-ul[data-sc-content=glossary] .gloss-sc-li {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
:root[data-glossary-layout-mode=compact] .gloss-sc-ul[data-sc-content=glossary] .gloss-sc-li:not(:first-child)::before {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
content: var(--compact-list-separator);
|
||||||
|
display: inline;
|
||||||
|
color: var(--text-color-light3);
|
||||||
|
}
|
||||||
|
@ -51,6 +51,10 @@
|
|||||||
},
|
},
|
||||||
"data": {
|
"data": {
|
||||||
"$ref": "#/definitions/structuredContentData"
|
"$ref": "#/definitions/structuredContentData"
|
||||||
|
},
|
||||||
|
"lang": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Defines the language of an element in the format defined by RFC 5646."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -82,6 +86,10 @@
|
|||||||
},
|
},
|
||||||
"style": {
|
"style": {
|
||||||
"$ref": "#/definitions/structuredContentStyle"
|
"$ref": "#/definitions/structuredContentStyle"
|
||||||
|
},
|
||||||
|
"lang": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Defines the language of an element in the format defined by RFC 5646."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -95,7 +103,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"tag": {
|
"tag": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["span", "div"]
|
"enum": ["span", "div", "ol", "ul", "li"]
|
||||||
},
|
},
|
||||||
"content": {
|
"content": {
|
||||||
"$ref": "#/definitions/structuredContent"
|
"$ref": "#/definitions/structuredContent"
|
||||||
@ -105,6 +113,10 @@
|
|||||||
},
|
},
|
||||||
"style": {
|
"style": {
|
||||||
"$ref": "#/definitions/structuredContentStyle"
|
"$ref": "#/definitions/structuredContentStyle"
|
||||||
|
},
|
||||||
|
"lang": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Defines the language of an element in the format defined by RFC 5646."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -206,6 +218,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The URL for the link. URLs starting with a ? are treated as internal links to other dictionary content.",
|
"description": "The URL for the link. URLs starting with a ? are treated as internal links to other dictionary content.",
|
||||||
"pattern": "^(?:https?:|\\?)[\\w\\W]*"
|
"pattern": "^(?:https?:|\\?)[\\w\\W]*"
|
||||||
|
},
|
||||||
|
"lang": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Defines the language of an element in the format defined by RFC 5646."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,6 +292,10 @@
|
|||||||
"marginBottom": {
|
"marginBottom": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 0
|
"default": 0
|
||||||
|
},
|
||||||
|
"listStyleType": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "disc"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,9 @@ class StructuredContentGenerator {
|
|||||||
return this._createStructuredContentElement(tag, content, dictionary, 'table-cell', true, true);
|
return this._createStructuredContentElement(tag, content, dictionary, 'table-cell', true, true);
|
||||||
case 'div':
|
case 'div':
|
||||||
case 'span':
|
case 'span':
|
||||||
|
case 'ol':
|
||||||
|
case 'ul':
|
||||||
|
case 'li':
|
||||||
return this._createStructuredContentElement(tag, content, dictionary, 'simple', true, true);
|
return this._createStructuredContentElement(tag, content, dictionary, 'simple', true, true);
|
||||||
case 'img':
|
case 'img':
|
||||||
return this.createDefinitionImage(content, dictionary);
|
return this.createDefinitionImage(content, dictionary);
|
||||||
@ -204,8 +207,9 @@ class StructuredContentGenerator {
|
|||||||
|
|
||||||
_createStructuredContentElement(tag, content, dictionary, type, hasChildren, hasStyle) {
|
_createStructuredContentElement(tag, content, dictionary, type, hasChildren, hasStyle) {
|
||||||
const node = this._createElement(tag, `gloss-sc-${tag}`);
|
const node = this._createElement(tag, `gloss-sc-${tag}`);
|
||||||
const {data} = content;
|
const {data, lang} = content;
|
||||||
if (typeof data === 'object' && data !== null) { this._setElementDataset(node, data); }
|
if (typeof data === 'object' && data !== null) { this._setElementDataset(node, data); }
|
||||||
|
if (typeof lang === 'string') { node.lang = lang; }
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'table-cell':
|
case 'table-cell':
|
||||||
{
|
{
|
||||||
@ -239,7 +243,8 @@ class StructuredContentGenerator {
|
|||||||
marginTop,
|
marginTop,
|
||||||
marginLeft,
|
marginLeft,
|
||||||
marginRight,
|
marginRight,
|
||||||
marginBottom
|
marginBottom,
|
||||||
|
listStyleType
|
||||||
} = contentStyle;
|
} = contentStyle;
|
||||||
if (typeof fontStyle === 'string') { style.fontStyle = fontStyle; }
|
if (typeof fontStyle === 'string') { style.fontStyle = fontStyle; }
|
||||||
if (typeof fontWeight === 'string') { style.fontWeight = fontWeight; }
|
if (typeof fontWeight === 'string') { style.fontWeight = fontWeight; }
|
||||||
@ -254,6 +259,7 @@ class StructuredContentGenerator {
|
|||||||
if (typeof marginLeft === 'number') { style.marginLeft = `${marginLeft}em`; }
|
if (typeof marginLeft === 'number') { style.marginLeft = `${marginLeft}em`; }
|
||||||
if (typeof marginRight === 'number') { style.marginRight = `${marginRight}em`; }
|
if (typeof marginRight === 'number') { style.marginRight = `${marginRight}em`; }
|
||||||
if (typeof marginBottom === 'number') { style.marginBottom = `${marginBottom}em`; }
|
if (typeof marginBottom === 'number') { style.marginBottom = `${marginBottom}em`; }
|
||||||
|
if (typeof listStyleType === 'string') { style.listStyleType = listStyleType; }
|
||||||
}
|
}
|
||||||
|
|
||||||
_createLinkElement(content, dictionary) {
|
_createLinkElement(content, dictionary) {
|
||||||
@ -269,6 +275,9 @@ class StructuredContentGenerator {
|
|||||||
const text = this._createElement('span', 'gloss-link-text');
|
const text = this._createElement('span', 'gloss-link-text');
|
||||||
node.appendChild(text);
|
node.appendChild(text);
|
||||||
|
|
||||||
|
const {lang} = content;
|
||||||
|
if (typeof lang === 'string') { node.lang = lang; }
|
||||||
|
|
||||||
const child = this.createStructuredContent(content.content, dictionary);
|
const child = this.createStructuredContent(content.content, dictionary);
|
||||||
if (child !== null) { text.appendChild(child); }
|
if (child !== null) { text.appendChild(child); }
|
||||||
|
|
||||||
|
@ -204,6 +204,105 @@
|
|||||||
"external link"
|
"external link"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
]},
|
||||||
|
{"type": "structured-content", "content": [
|
||||||
|
{"tag": "ul", "content": [
|
||||||
|
{"tag": "li", "content": "Unordered list item 1"},
|
||||||
|
{"tag": "li", "content": "Unordered list item 2"},
|
||||||
|
{"tag": "li", "content": "Unordered list item 3"}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{"type": "structured-content", "content": [
|
||||||
|
{"tag": "ol", "content": [
|
||||||
|
{"tag": "li", "content": "Ordered list item 1"},
|
||||||
|
{"tag": "li", "content": "Ordered list item 2"},
|
||||||
|
{"tag": "li", "content": "Ordered list item 3"}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{"type": "structured-content", "content": [
|
||||||
|
{"tag": "ol", "style": {"listStyleType": "hiragana-iroha"}, "content": [
|
||||||
|
{"tag": "li", "content": "List item i"},
|
||||||
|
{"tag": "li", "content": "List item ro"},
|
||||||
|
{"tag": "li", "content": "List item ha"}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{"type": "structured-content", "content": [
|
||||||
|
{"tag": "ul", "content": [
|
||||||
|
{"tag": "li", "style": {"listStyleType": "'⇄'"}, "content": ["【", {"tag": "a", "href": "?query=よみ&wildcards=off", "content": ["Antonym"]}, "】"]},
|
||||||
|
{"tag": "li", "style": {"listStyleType": "'🔄'"}, "content": ["【", {"tag": "a", "href": "?query=よみ&wildcards=off", "content": ["References and is referenced by"]}, "】"]},
|
||||||
|
{"tag": "li", "style": {"listStyleType": "'➡'"}, "content": ["【", {"tag": "a", "href": "?query=よみ&wildcards=off", "content": ["References"]}, "】"]},
|
||||||
|
{"tag": "li", "style": {"listStyleType": "'⬅'"}, "content": ["【", {"tag": "a", "href": "?query=よみ&wildcards=off", "content": ["Referenced by"]}, "】"]}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{"type": "structured-content", "content": [
|
||||||
|
{"tag": "ol", "content": [
|
||||||
|
{"tag": "li", "style": {"listStyleType": "'①'"}, "content": "まるいち"},
|
||||||
|
{"tag": "li", "style": {"listStyleType": "'②'"}, "content": "まるに"},
|
||||||
|
{"tag": "li", "style": {"listStyleType": "'③'"}, "content": "まるさん"},
|
||||||
|
{"tag": "li", "style": {"listStyleType": "'④'"}, "content": "まるよん"}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{"type": "structured-content", "content": [
|
||||||
|
{"tag": "div", "lang": "?????", "style": {"fontSize": "xxx-large"}, "content": "直次茶冷 (invalid lang)"},
|
||||||
|
{"tag": "div", "lang": "ja-JP", "style": {"fontSize": "xxx-large"}, "content": "直次茶冷 (lang=ja-JP)"},
|
||||||
|
{"tag": "div", "lang": "zh-CN", "style": {"fontSize": "xxx-large"}, "content": "直次茶冷 (lang=zh-CN)"},
|
||||||
|
{"tag": "div", "lang": "zh-TW", "style": {"fontSize": "xxx-large"}, "content": "直次茶冷 (lang=zh-TW)"}
|
||||||
|
]},
|
||||||
|
{"type": "structured-content", "content": [
|
||||||
|
{"tag": "ul", "style": {"listStyleType": "japanese-formal"}, "content": [
|
||||||
|
{"tag": "li", "content": ["【", {"tag": "a", "href": "?query=直次茶冷&wildcards=off", "content": "直次茶冷"}, "】(default)"]},
|
||||||
|
{"tag": "li", "content": ["【", {"tag": "a", "href": "?query=直次茶冷&wildcards=off", "content": "直次茶冷", "lang": "ja"}, "】(lang=ja)"]},
|
||||||
|
{"tag": "li", "content": ["【", {"tag": "a", "href": "?query=直次茶冷&wildcards=off", "content": "直次茶冷", "lang": "zh-CN"}, "】(lang=zh-CN)"]},
|
||||||
|
{"tag": "li", "content": ["【", {"tag": "a", "href": "?query=直次茶冷&wildcards=off", "content": "直次茶冷", "lang": "zh-TW"}, "】(lang=zh-TW)"]}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{"type": "structured-content", "content": [
|
||||||
|
{"tag": "table", "lang": "", "content": [
|
||||||
|
{"tag": "thead", "content": [
|
||||||
|
{"tag": "tr", "content": [
|
||||||
|
{"tag": "th", "content": "JP"},
|
||||||
|
{"tag": "th", "content": "SC"},
|
||||||
|
{"tag": "th", "content": "TC"},
|
||||||
|
{"tag": "th", "content": "??"}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{"tag": "tbody", "content": [
|
||||||
|
{"tag": "tr", "content": [
|
||||||
|
{"tag": "td", "lang": "ja-JP", "content": "直次茶冷"},
|
||||||
|
{"tag": "td", "lang": "zh-CN", "content": "直次茶冷"},
|
||||||
|
{"tag": "td", "lang": "zh-TW", "content": "直次茶冷"},
|
||||||
|
{"tag": "td", "content": "直次茶冷"}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{"type": "structured-content", "content": [
|
||||||
|
{"tag": "table", "lang": "ja", "content": [
|
||||||
|
{"tag": "thead", "content": [
|
||||||
|
{"tag": "tr", "content": [
|
||||||
|
{"tag": "th", "content": "lang=ja applied to whole table"}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{"tag": "tbody", "content": [
|
||||||
|
{"tag": "tr", "content": [
|
||||||
|
{"tag": "td", "content": "直次茶冷"}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{"type": "structured-content", "content": [
|
||||||
|
{"tag": "table", "lang": "zh-CN", "content": [
|
||||||
|
{"tag": "thead", "content": [
|
||||||
|
{"tag": "tr", "content": [
|
||||||
|
{"tag": "th", "content": "lang=zh-CN applied to whole table"}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{"tag": "tbody", "content": [
|
||||||
|
{"tag": "tr", "content": [
|
||||||
|
{"tag": "td", "content": "直次茶冷"}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
100, "P E1"
|
100, "P E1"
|
||||||
|
Loading…
Reference in New Issue
Block a user