diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2021-06-25 17:24:29 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-06-25 17:24:29 -0400 | 
| commit | 5756885fa9340f087a168d40c8d0d10a3a8fe4d5 (patch) | |
| tree | e960821662a12b70430590c9ea4f43b1abc4d54c | |
| parent | cf70b3de6411cfd540f2c3c7f6e1c27afb10ef84 (diff) | |
Structured content updates (#1753)
* Update schema
* Update content generation
* Update styles
* Update test data
* Update style names
| -rw-r--r-- | ext/css/display.css | 26 | ||||
| -rw-r--r-- | ext/css/material.css | 2 | ||||
| -rw-r--r-- | ext/data/schemas/dictionary-term-bank-v3-schema.json | 107 | ||||
| -rw-r--r-- | ext/js/display/display-generator.js | 71 | ||||
| -rw-r--r-- | test/data/dictionaries/valid-dictionary1/term_bank_1.json | 73 | 
5 files changed, 270 insertions, 9 deletions
| diff --git a/ext/css/display.css b/ext/css/display.css index 45658f19..e1efb223 100644 --- a/ext/css/display.css +++ b/ext/css/display.css @@ -1726,6 +1726,32 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con  } +/* Structured content glossary styles */ +.gloss-sc-table-container { +    display: block; +} +.gloss-sc-table { +    table-layout: auto; +    border-collapse: collapse; +    border-spacing: 0; +} +.gloss-sc-tbody { +    background-color: transparent; +} +.gloss-sc-thead, +.gloss-sc-tfoot, +.gloss-sc-th { +    font-weight: bold; +    background-color: var(--background-color-dark1); +} +.gloss-sc-th, +.gloss-sc-td { +    border: calc(1em / var(--font-size-no-units)) solid var(--text-color-light2); +    padding: 0.25em; +    vertical-align: top; +} + +  /* Kanji */  .kanji-glyph-container {      display: block; diff --git a/ext/css/material.css b/ext/css/material.css index dd135065..b19b0b0f 100644 --- a/ext/css/material.css +++ b/ext/css/material.css @@ -69,6 +69,7 @@      --text-color-light4: #888888;      --background-color: #f8f9fa;      --background-color-light: #ffffff; +    --background-color-dark1: #eeeeee;      --shadow-color: rgba(0, 0, 0, 0.185);      --shadow-color-off: rgba(0, 0, 0, 0); @@ -128,6 +129,7 @@      --text-color-light4: #777777;      --background-color: #1e1e1e;      --background-color-light: #0a0a0a; +    --background-color-dark1: #333333;      --shadow-color: rgba(255, 255, 255, 0.185);      --shadow-color-off: rgba(255, 255, 255, 0); diff --git a/ext/data/schemas/dictionary-term-bank-v3-schema.json b/ext/data/schemas/dictionary-term-bank-v3-schema.json index fd3f3844..af4494ff 100644 --- a/ext/data/schemas/dictionary-term-bank-v3-schema.json +++ b/ext/data/schemas/dictionary-term-bank-v3-schema.json @@ -19,6 +19,20 @@                      "oneOf": [                          {                              "type": "object", +                            "description": "Empty tags.", +                            "required": [ +                                "tag" +                            ], +                            "additionalProperties": false, +                            "properties": { +                                "tag": { +                                    "type": "string", +                                    "enum": ["br"] +                                } +                            } +                        }, +                        { +                            "type": "object",                              "description": "Generic container tags.",                              "required": [                                  "tag" @@ -27,10 +41,58 @@                              "properties": {                                  "tag": {                                      "type": "string", -                                    "enum": ["ruby", "rt", "rp"] +                                    "enum": ["ruby", "rt", "rp", "table", "thead", "tbody", "tfoot", "tr"] +                                }, +                                "content": { +                                    "$ref": "#/definitions/structuredContent" +                                } +                            } +                        }, +                        { +                            "type": "object", +                            "description": "Table tags.", +                            "required": [ +                                "tag" +                            ], +                            "additionalProperties": false, +                            "properties": { +                                "tag": { +                                    "type": "string", +                                    "enum": ["td", "th"] +                                }, +                                "content": { +                                    "$ref": "#/definitions/structuredContent" +                                }, +                                "colSpan": { +                                    "type": "integer", +                                    "minimum": 1 +                                }, +                                "rowSpan": { +                                    "type": "integer", +                                    "minimum": 1 +                                }, +                                "style": { +                                    "$ref": "#/definitions/structuredContentStyle" +                                } +                            } +                        }, +                        { +                            "type": "object", +                            "description": "Container tags supporting configurable styles.", +                            "required": [ +                                "tag" +                            ], +                            "additionalProperties": false, +                            "properties": { +                                "tag": { +                                    "type": "string", +                                    "enum": ["span", "div"]                                  },                                  "content": {                                      "$ref": "#/definitions/structuredContent" +                                }, +                                "style": { +                                    "$ref": "#/definitions/structuredContentStyle"                                  }                              }                          }, @@ -112,6 +174,49 @@                      ]                  }              ] +        }, +        "structuredContentStyle": { +            "type": "object", +            "additionalProperties": false, +            "properties": { +                "fontStyle": { +                    "type": "string", +                    "enum": ["normal", "italic"], +                    "default": "normal" +                }, +                "fontWeight": { +                    "type": "string", +                    "enum": ["normal", "bold"], +                    "default": "normal" +                }, +                "fontSize": { +                    "type": "string", +                    "enum": ["xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "xxx-large"], +                    "default": "medium" +                }, +                "textDecorationLine": { +                    "oneOf": [ +                        { +                            "type": "string", +                            "enum": ["none", "underline", "overline", "line-through"], +                            "default": "none" +                        }, +                        { +                            "type": "array", +                            "items": { +                                "type": "string", +                                "enum": ["underline", "overline", "line-through"], +                                "default": "none" +                            } +                        } +                    ] +                }, +                "verticalAlign": { +                    "type": "string", +                    "enum": ["baseline", "sub", "super", "text-top", "text-bottom", "middle", "top", "bottom"], +                    "default": "baseline" +                } +            }          }      },      "type": "array", diff --git a/ext/js/display/display-generator.js b/ext/js/display/display-generator.js index 6a5b26f1..7de65f78 100644 --- a/ext/js/display/display-generator.js +++ b/ext/js/display/display-generator.js @@ -442,23 +442,78 @@ class DisplayGenerator {          }          const {tag} = content;          switch (tag) { +            case 'br': +                return this._createStructuredContentElement(tag, content, dictionary, 'simple', false, false);              case 'ruby':              case 'rt':              case 'rp': -            { -                const node = document.createElement(tag); -                const child = this._createStructuredContent(content.content, dictionary); -                if (child !== null) { -                    node.appendChild(child); -                } -                return node; -            } +                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': +                return this._createStructuredContentElement(tag, content, dictionary, 'simple', true, true);              case 'img':                  return this._createDefinitionImage(content, dictionary);          }          return null;      } +    _createStructuredContentTableElement(tag, content, dictionary) { +        const container = document.createElement('div'); +        container.classList = 'gloss-sc-table-container'; +        const table = this._createStructuredContentElement(tag, content, dictionary, 'table', true, false); +        container.appendChild(table); +        return container; +    } + +    _createStructuredContentElement(tag, content, dictionary, type, hasChildren, hasStyle) { +        const node = document.createElement(tag); +        node.className = `gloss-sc-${tag}`; +        switch (type) { +            case 'table-cell': +                { +                    const {colSpan, rowSpan} = content; +                    if (typeof colSpan === 'number') { node.colSpan = colSpan; } +                    if (typeof rowSpan === 'number') { node.rowSpan = rowSpan; } +                } +                break; +        } +        if (hasStyle) { +            const {style} = content; +            if (typeof style === 'object' && style !== null) { +                this._setStructuredContentElementStyle(node, style); +            } +        } +        if (hasChildren) { +            const child = this._createStructuredContent(content.content, dictionary); +            if (child !== null) { node.appendChild(child); } +        } +        return node; +    } + +    _setStructuredContentElementStyle(node, contentStyle) { +        const {style} = node; +        const {fontStyle, fontWeight, fontSize, textDecorationLine, verticalAlign} = contentStyle; +        if (typeof fontStyle === 'string') { style.fontStyle = fontStyle; } +        if (typeof fontWeight === 'string') { style.fontWeight = fontWeight; } +        if (typeof fontSize === 'string') { style.fontSize = fontSize; } +        if (typeof verticalAlign === 'string') { style.verticalAlign = verticalAlign; } +        if (typeof textDecorationLine === 'string') { +            style.textDecoration = textDecorationLine; +        } else if (Array.isArray(textDecorationLine)) { +            style.textDecoration = textDecorationLine.join(' '); +        } +    } +      _createTermDisambiguation(disambiguation) {          const node = this._templates.instantiate('definition-disambiguation');          node.dataset.term = disambiguation; diff --git a/test/data/dictionaries/valid-dictionary1/term_bank_1.json b/test/data/dictionaries/valid-dictionary1/term_bank_1.json index 1ba70c26..c58a17bf 100644 --- a/test/data/dictionaries/valid-dictionary1/term_bank_1.json +++ b/test/data/dictionaries/valid-dictionary1/term_bank_1.json @@ -59,6 +59,79 @@                  "莢 ",                  {"tag": "img", "path": "character.gif", "width": 1, "height": 1, "imageRendering": "crisp-edges", "background": false, "appearance": "monochrome", "collapsible": false, "collapsed": false, "sizeUnits": "em"},                  "莢\n" +            ]}, +            {"type": "structured-content", "content": [ +                {"tag": "div", "style": {"fontStyle": "normal"}, "content": "fontStyle:normal"}, +                {"tag": "div", "style": {"fontStyle": "italic"}, "content": "fontStyle:italic"}, +                {"tag": "div", "style": {"fontWeight": "normal"}, "content": "fontWeight:normal"}, +                {"tag": "div", "style": {"fontWeight": "bold"}, "content": "fontWeight:bold"}, +                {"tag": "div", "style": {"fontSize": "xx-small"}, "content": "fontSize:xx-small"}, +                {"tag": "div", "style": {"fontSize": "x-small"}, "content": "fontSize:x-small"}, +                {"tag": "div", "style": {"fontSize": "small"}, "content": "fontSize:small"}, +                {"tag": "div", "style": {"fontSize": "medium"}, "content": "fontSize:medium"}, +                {"tag": "div", "style": {"fontSize": "large"}, "content": "fontSize:large"}, +                {"tag": "div", "style": {"fontSize": "x-large"}, "content": "fontSize:x-large"}, +                {"tag": "div", "style": {"fontSize": "xx-large"}, "content": "fontSize:xx-large"}, +                {"tag": "div", "style": {"fontSize": "xxx-large"}, "content": "fontSize:xxx-large"}, +                {"tag": "div", "style": {"textDecorationLine": "none"}, "content": "textDecorationLine:none "}, +                {"tag": "div", "style": {"textDecorationLine": "underline"}, "content": "textDecorationLine:underline "}, +                {"tag": "div", "style": {"textDecorationLine": "overline"}, "content": "textDecorationLine:overline "}, +                {"tag": "div", "style": {"textDecorationLine": "line-through"}, "content": "textDecorationLine:line-through "}, +                {"tag": "div", "style": {"textDecorationLine": ["underline", "overline", "line-through"]}, "content": "textDecorationLine:[underline,overline,line-through] "}, +                {"tag": "div", "content": ["baseline ", {"tag": "span", "style": {"verticalAlign": "baseline"}, "content": "verticalAlign:baseline "}]}, +                {"tag": "div", "content": ["baseline ", {"tag": "span", "style": {"verticalAlign": "sub"}, "content": "verticalAlign:sub "}]}, +                {"tag": "div", "content": ["baseline ", {"tag": "span", "style": {"verticalAlign": "super"}, "content": "verticalAlign:super "}]}, +                {"tag": "div", "content": ["baseline ", {"tag": "span", "style": {"verticalAlign": "text-top"}, "content": "verticalAlign:text-top "}]}, +                {"tag": "div", "content": ["baseline ", {"tag": "span", "style": {"verticalAlign": "text-bottom"}, "content": "verticalAlign:text-bottom "}]}, +                {"tag": "div", "content": ["baseline ", {"tag": "span", "style": {"verticalAlign": "middle"}, "content": "verticalAlign:middle "}]}, +                {"tag": "div", "content": ["baseline ", {"tag": "span", "style": {"verticalAlign": "top"}, "content": "verticalAlign:top "}]}, +                {"tag": "div", "content": ["baseline ", {"tag": "span", "style": {"verticalAlign": "bottom"}, "content": "verticalAlign:bottom "}]} +            ]}, +            {"type": "structured-content", "content": [ +                "br", +                {"tag": "br"}, +                "br" +            ]}, +            {"type": "structured-content", "content": [ +                {"tag": "table", "content": [ +                    {"tag": "thead", "content": [ +                        {"tag": "tr", "content": [ +                            {"tag": "th", "content": "Header 1"}, +                            {"tag": "th", "content": "Header 2"}, +                            {"tag": "th", "content": "Header 3"}, +                            {"tag": "th", "content": "Header 4"} +                        ]} +                    ]}, +                    {"tag": "tbody", "content": [ +                        {"tag": "tr", "content": [ +                            {"tag": "td", "content": "Cell A1"}, +                            {"tag": "td", "content": "Cell B1"}, +                            {"tag": "td", "content": "Cell C1"}, +                            {"tag": "td", "content": "Cell D1"} +                        ]}, +                        {"tag": "tr", "content": [ +                            {"tag": "td", "content": "Cell A2"}, +                            {"tag": "td", "content": "Cell B2"}, +                            {"tag": "td", "content": "Cell C2:D2", "colSpan": 2} +                        ]}, +                        {"tag": "tr", "content": [ +                            {"tag": "td", "content": "Cell A3"}, +                            {"tag": "td", "content": "Cell B3\nCell B4", "rowSpan": 2}, +                            {"tag": "td", "content": "Cell C3:D3\nCell C4:D4", "rowSpan": 2, "colSpan": 2} +                        ]}, +                        {"tag": "tr", "content": [ +                            {"tag": "td", "content": "Cell A4"} +                        ]} +                    ]}, +                    {"tag": "tfoot", "content": [ +                        {"tag": "tr", "content": [ +                            {"tag": "th", "content": "Footer 1"}, +                            {"tag": "th", "content": "Footer 2"}, +                            {"tag": "th", "content": "Footer 3"}, +                            {"tag": "th", "content": "Footer 4"} +                        ]} +                    ]} +                ]}              ]}          ],          9, "P E1" |