From 766387efa3d9733e0f8966c4ea028b0ae06ac780 Mon Sep 17 00:00:00 2001 From: stephenmk Date: Mon, 11 Dec 2023 21:15:00 -0600 Subject: [PATCH 1/3] Add support for alt attribute on structured content images --- ext/css/structured-content.css | 2 +- ext/data/structured-content-style.json | 2 +- .../sandbox/structured-content-generator.js | 3 ++- .../valid-dictionary1/aosaba_auto.png | Bin 0 -> 1699 bytes .../valid-dictionary1/aosaba_mono.png | Bin 0 -> 1807 bytes .../valid-dictionary1/term_bank_1.json | 9 ++++++++- 6 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 test/data/dictionaries/valid-dictionary1/aosaba_auto.png create mode 100644 test/data/dictionaries/valid-dictionary1/aosaba_mono.png diff --git a/ext/css/structured-content.css b/ext/css/structured-content.css index 1d4677b5eb..50fcad028c 100644 --- a/ext/css/structured-content.css +++ b/ext/css/structured-content.css @@ -147,7 +147,7 @@ } .gloss-image-link[data-appearance=monochrome] .gloss-image { - visibility: hidden; + opacity: 0; } .gloss-image-link:not([data-appearance=monochrome]) .gloss-image-background { display: none; diff --git a/ext/data/structured-content-style.json b/ext/data/structured-content-style.json index fe222486dc..52bd41c895 100644 --- a/ext/data/structured-content-style.json +++ b/ext/data/structured-content-style.json @@ -169,7 +169,7 @@ { "selectors": [".gloss-image-link[data-appearance=monochrome] .gloss-image"], "styles": [ - ["visibility", "hidden"] + ["opacity", "0"] ] }, { diff --git a/ext/js/display/sandbox/structured-content-generator.js b/ext/js/display/sandbox/structured-content-generator.js index 5a91b01c38..60aaf32341 100644 --- a/ext/js/display/sandbox/structured-content-generator.js +++ b/ext/js/display/sandbox/structured-content-generator.js @@ -65,6 +65,7 @@ export class StructuredContentGenerator { preferredWidth, preferredHeight, title, + description, pixelated, imageRendering, appearance, @@ -102,7 +103,7 @@ export class StructuredContentGenerator { imageContainer.appendChild(imageBackground); const image = /** @type {HTMLImageElement} */ (this._createElement('img', 'gloss-image')); - image.alt = ''; + image.alt = typeof description === 'string' ? description : ''; imageContainer.appendChild(image); const overlay = this._createElement('span', 'gloss-image-container-overlay'); diff --git a/test/data/dictionaries/valid-dictionary1/aosaba_auto.png b/test/data/dictionaries/valid-dictionary1/aosaba_auto.png new file mode 100644 index 0000000000000000000000000000000000000000..ddef36ac8894b3388999961439c992da99ed5232 GIT binary patch literal 1699 zcmV;U23+}xP)pLRY^oaRCwC#+GCL9TolIfwQbw`+O}=mwr#C#+qP}nw#}LI{y*Fg zr%ol)oyPQR?R3>|k#mwxKb=Z$IyXc5EBzJTOEP4*9F6e>9!7~&df(i*A6KAsA_Mpp zVoXAnIKOWNh;jg9@MLNSFcD&`$0eq(Ry+exRv}|*efS(W0dY>@PGmBD58*7ni(>%m z@FDUB*v1vn?!?UyWspbD#WJ5TYdGg`hi7#;qt$3y+?BIH`IL;UAQA_4n~l zgjzt9kzuYk3gY1ut_Tvq$0orV9zD-Nl&4Mo2S^%m3?+gDFc0Dk_37!adZy^ZKCvgk z=->Pjh;oO|NbQ(9KU}QJ=X?N7^*8I&^P=i$=GBv+li&|1AI%#VRM+)nT<6m_3xW;E z8|JnfqZMk!BLI3nR9B%ZA`ReMh|}Ar=SmgOZKjqHclfN=0fHn9$3wW>$Ab{%FH^Uk z!5P(m6!!-G@VT%{wuK774r=y5V(e9)08Yg696-H<=^uguLB9R}AjUF$ zZJf~Gu&H(SI0SD`Pyn9<`S4Y73WCEBXMjiV0ad@m)E+Uz;+n3Mb_1X>qZ&W=M#mTh zupz`r@FWVR;9`jKS&07Xkp}P@1oM#_9pWEAd;|`Frp#E2Z7A)QrB(oEVthB)B+?_G z5-xTBjeh`X@g(TClj#AZ2aq1XYW!oIRQ2|z*6*A<3C7`4mAK1b90C}Ig2q8rzsb~| zPy9gWJUR!k>?2&{{+$>9C^w|V0G?Dk_(wDWxLffcq5ezr|D^We+0k}KNxnWw2bq+^txK=@^bKsE@Dlikdf67TG=a?`|YRlqVw% zU;*ATj;Z?Zrq3BUAxfi!4u#!G>InLTxeq0<1n(nj z1OZeuzis{%X#f*&c>tgLT?O2*xnzI<=Br6jk3|r|U6_FZC>gVJfPKaBGME?BAWkpj zk9>=94uIaGD1ghI3&ULRPIN;n{D{Yq*VT$)Bg9#P(tb0-aCfX`Xclzxgt^YOIF9xx z5Tf@bJf;5s4#YT!TCRSZsVzockL?bEpg&5*`zU!81CUeAC!7SqcHEZ2x*KpJL;ypP zPxbUO^#(rYjkOT$#iP+ojT?u2?*I2;6RuZ1zd&5-nccF&Y7lY?PkU^;6a;%y2;dfv z^{)3AFXZ;M4d(_7dYJQ;U;?Cw(5mY)B!10zUh- z-1J@H)AxeuYaHp^;A_-1T%21~-*ENY-sNif95YNUu4=O(m>59-pPRm#>d>!?imG>@ z>HR9mbHZH^+^3fBg`kI8_BOlQWJh1Oe@)F*MDUYZRtrgHF2ZHu z1W+5|+^d$aR=?vFQgehwxzH^yX~yC`kj>2A{2)jGA@=zbuhE_hOO%lr!kuK~+-xUA zIghzzS#et57pVSe`izZ#AxgCv2GGV{8T7eJNk*wqhyNmobFr#T^}4Yzx1PPtpkyH? zpglxc;o4#qz)}d>ndMorAEG>w(uVFf%>`9W2Qxw~*N624k3bthjJHArP$a;IFK^F7 zrrss2r%M!ao6F2@Q{Ss<^L%bQo0)YUgcxg(!|T$hJQCok_DD0E{Z$lIJr6;YJHx#N z9-wOZO>L&CU5aVwWhWx*ha}D^`&+#lXo+$XW8FTrLLK~rM(+QEuu`39tt8}7+y4Wz z@eeY3efVcX%~s-Fj1Nubl@}GhVy}YYIneRKeCYlr tHgYT$0OA_xLS{RL5dcQPC>RB!006DRCPXX6Ny-2K002ovPDHLkV1gB9CSU*n literal 0 HcmV?d00001 diff --git a/test/data/dictionaries/valid-dictionary1/aosaba_mono.png b/test/data/dictionaries/valid-dictionary1/aosaba_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..a07760987578c0488fe99d647452799aac3a0ea8 GIT binary patch literal 1807 zcmV+q2k`ibP)pL!AV3xRCwC#S_5z`O%n~CZCn5U*|u%lwr%U#wr$(CZQDLw)u}qw zwVS(pvzyJUq^nLPGt+aY_snch?@T9nmMqDVOOlcj>f-OGzym-jAUz~6a1U@PP!@x710JHm zkD%^0Aj#<6kGA9Z`*nx}tU%p+Kz_ihTneN~ZZJmlanQK{_4`tE@XFLvf&wJ~OjC~0xa_lAJEc)+d<)NNoLCE?GA38;ZSd#LZH@xK2P$%x~?P6wROcE%>@9uWb# zp+DQ$a}xE>0=}f2bfj5r=uV4y^hz$GrY&%_qLn|6yQp?8e>>_^>QfG^1- z?9sMS&E-K_t5J2Gf+r>BTXzCN2a`|*@GPHE=c6#Vmc#=OjB-&je^tvn}XZ!0*1~LcpPbeLyKQc0be=^5gmc){cw? zX!?R7hVu+_8_I1Rmf$T>5PTE(?~#Bz5F<-EA=|SO7sMT zd?r}gT;5F3BfQK(fJ!zwEa5v0l$)bIUuGa6Q5|40=nQ0iV6iyH$O+KMRAdlXW#G%5|a+g^THJQ#Y!M^^oh7gM#1O!8Jy6;Q z0W&En>S4gI+>XAJ^ffLWm=CZL;x?FH0vnpeE~qOA#3|tuP#h>ktKmG4{cgjU9rV)l zJKzzzY%KvBR+ByRQc0S;6u2X(49&s{uhG<1Fz%q74|uqZc^-J2%5OUOkKJ^Ge6vl| zB7%5#>Z9#FQ7i+5Dlh5k$W8f#W7L3+d}GW)F~K1>0w^P;0QKo%ym~Dczp-3(wxj$| zT2kXikO6l~REEFTkj{^kH<+w-MJWh5Lis{0WynBB0#LpYuyT!!7j&gssY-FmNwE`1 z^y>pUsv*_2>K4imPM~-5h{G2102z701R#6~vnmw=3c0MDg+|XU0peM+TI$A?8;pOi z)T&}M=uM`NLPytTc~##_b@t4Tw!P9Eiz{h4IC~T2cl{IKDjzyUdqS2yRrc~@?~x%l*n}tnMP=EA zS^h2{eGXu10e_i?tPvCe`0ZvcJHssw>9S>FE&n-W$OZI3oEu@26&Z< z#t+%m(a!7bQeLyoY&9%zr?wgV+3A)nNoj73WfC+QJ?k_d^m?l;?=@$$Yd%tO(z)OK z_HAC`fBOwk(6mjawu|I_*AEq&i2RJr)^<6ozuV{?28N4GKoj5}Jw~r1Wes^3v!gXQ z!6eJ^yKKMm8*V|-Q*N1E^pG4_bV%?f`DowYtS326Qh^>O2#oa`_zbj%k0#9gpIK%% z0Dhz>knCYA+ZVvYuh0O=|2CpH;o>Qu=j*1BB%el_A7iZl)PeN{hAAee{4c&o(Ol09 xKhTNE0r-|ez_%JRpPn7V2mqsC6pVsV006d~AiqJ%Ksf*a002ovPDHLkV1md(W#s?> literal 0 HcmV?d00001 diff --git a/test/data/dictionaries/valid-dictionary1/term_bank_1.json b/test/data/dictionaries/valid-dictionary1/term_bank_1.json index 38b022fad1..e57e33d455 100644 --- a/test/data/dictionaries/valid-dictionary1/term_bank_1.json +++ b/test/data/dictionaries/valid-dictionary1/term_bank_1.json @@ -66,7 +66,7 @@ "莢\n" ]}, {"type": "structured-content", "content": [ - "Imgae aspect ratio tests:\nあ", + "Image aspect ratio tests:\nあ", {"tag": "img", "path": "character2.gif", "height": 1.1, "imageRendering": "crisp-edges", "appearance": "monochrome", "background": false, "sizeUnits": "em", "collapsed": false, "collapsible": false}, "あ\nあ", {"tag": "img", "path": "character2.gif", "width": 0.4125, "imageRendering": "crisp-edges", "appearance": "monochrome", "background": false, "sizeUnits": "em", "collapsed": false, "collapsible": false}, @@ -76,6 +76,13 @@ {"tag": "img", "path": "character3.gif", "height": 0.4125, "imageRendering": "crisp-edges", "appearance": "monochrome", "background": false, "sizeUnits": "em", "collapsed": false, "collapsible": false}, "あ" ]}, + {"type": "structured-content", "content": [ + "Image alt text tests.\n𬵪 = Unicode character\n", + {"tag": "img", "description": "𬵪", "path": "aosaba_mono.png", "height": 1.0, "width": 1.0, "background": false, "sizeUnits": "em", "collapsed": false, "collapsible": false, "appearance": "monochrome"}, + " = monochrome PNG\n", + {"tag": "img", "description": "𬵪", "path": "aosaba_auto.png", "height": 1.0, "width": 1.0, "background": false, "sizeUnits": "em", "collapsed": false, "collapsible": false, "appearance": "auto"}, + " = color PNG" + ]}, {"type": "structured-content", "content": [ {"tag": "div", "style": {"fontStyle": "normal"}, "content": "fontStyle:normal"}, {"tag": "div", "style": {"fontStyle": "italic"}, "content": "fontStyle:italic"}, From fd373d6e534f15a0cd868e5cac63a33b951d343a Mon Sep 17 00:00:00 2001 From: stephenmk Date: Fri, 15 Dec 2023 19:06:45 -0600 Subject: [PATCH 2/3] Add new `alt` property for structured content images --- ext/data/schemas/dictionary-term-bank-v3-schema.json | 8 ++++++++ ext/js/display/sandbox/structured-content-generator.js | 4 ++-- ext/js/language/dictionary-importer.js | 2 ++ test/data/dictionaries/valid-dictionary1/term_bank_1.json | 4 ++-- types/ext/structured-content.d.ts | 4 ++++ 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/ext/data/schemas/dictionary-term-bank-v3-schema.json b/ext/data/schemas/dictionary-term-bank-v3-schema.json index 2fc39c2e3e..547bde49ed 100644 --- a/ext/data/schemas/dictionary-term-bank-v3-schema.json +++ b/ext/data/schemas/dictionary-term-bank-v3-schema.json @@ -155,6 +155,10 @@ "type": "string", "description": "Hover text for the image." }, + "alt": { + "type": "string", + "description": "Alt text for the image." + }, "description": { "type": "string", "description": "Description of the image." @@ -424,6 +428,10 @@ "type": "string", "description": "Hover text for the image." }, + "alt": { + "type": "string", + "description": "Alt text for the image." + }, "description": { "type": "string", "description": "Description of the image." diff --git a/ext/js/display/sandbox/structured-content-generator.js b/ext/js/display/sandbox/structured-content-generator.js index 60aaf32341..5846e9aa18 100644 --- a/ext/js/display/sandbox/structured-content-generator.js +++ b/ext/js/display/sandbox/structured-content-generator.js @@ -65,7 +65,7 @@ export class StructuredContentGenerator { preferredWidth, preferredHeight, title, - description, + alt, pixelated, imageRendering, appearance, @@ -103,7 +103,7 @@ export class StructuredContentGenerator { imageContainer.appendChild(imageBackground); const image = /** @type {HTMLImageElement} */ (this._createElement('img', 'gloss-image')); - image.alt = typeof description === 'string' ? description : ''; + image.alt = typeof alt === 'string' ? alt : ''; imageContainer.appendChild(image); const overlay = this._createElement('span', 'gloss-image-container-overlay'); diff --git a/ext/js/language/dictionary-importer.js b/ext/js/language/dictionary-importer.js index 08fcf86bbb..feba852d8f 100644 --- a/ext/js/language/dictionary-importer.js +++ b/ext/js/language/dictionary-importer.js @@ -498,6 +498,7 @@ export class DictionaryImporter { width: preferredWidth, height: preferredHeight, title, + alt, description, pixelated, imageRendering, @@ -513,6 +514,7 @@ export class DictionaryImporter { if (typeof preferredWidth === 'number') { target.preferredWidth = preferredWidth; } if (typeof preferredHeight === 'number') { target.preferredHeight = preferredHeight; } if (typeof title === 'string') { target.title = title; } + if (typeof alt === 'string') { target.alt = alt; } if (typeof description === 'string') { target.description = description; } if (typeof pixelated === 'boolean') { target.pixelated = pixelated; } if (typeof imageRendering === 'string') { target.imageRendering = imageRendering; } diff --git a/test/data/dictionaries/valid-dictionary1/term_bank_1.json b/test/data/dictionaries/valid-dictionary1/term_bank_1.json index e57e33d455..14f66d951c 100644 --- a/test/data/dictionaries/valid-dictionary1/term_bank_1.json +++ b/test/data/dictionaries/valid-dictionary1/term_bank_1.json @@ -78,9 +78,9 @@ ]}, {"type": "structured-content", "content": [ "Image alt text tests.\n𬵪 = Unicode character\n", - {"tag": "img", "description": "𬵪", "path": "aosaba_mono.png", "height": 1.0, "width": 1.0, "background": false, "sizeUnits": "em", "collapsed": false, "collapsible": false, "appearance": "monochrome"}, + {"tag": "img", "alt": "𬵪", "path": "aosaba_mono.png", "height": 1.0, "width": 1.0, "background": false, "sizeUnits": "em", "collapsed": false, "collapsible": false, "appearance": "monochrome"}, " = monochrome PNG\n", - {"tag": "img", "description": "𬵪", "path": "aosaba_auto.png", "height": 1.0, "width": 1.0, "background": false, "sizeUnits": "em", "collapsed": false, "collapsible": false, "appearance": "auto"}, + {"tag": "img", "alt": "𬵪", "path": "aosaba_auto.png", "height": 1.0, "width": 1.0, "background": false, "sizeUnits": "em", "collapsed": false, "collapsible": false, "appearance": "auto"}, " = color PNG" ]}, {"type": "structured-content", "content": [ diff --git a/types/ext/structured-content.d.ts b/types/ext/structured-content.d.ts index 09755c882c..cd69659bc3 100644 --- a/types/ext/structured-content.d.ts +++ b/types/ext/structured-content.d.ts @@ -133,6 +133,10 @@ export type ImageElementBase = { * Hover text for the image. */ title?: string; + /** + * Alt text for the image. + */ + alt?: string; /** * Description of the image. */ From 51739f0b3a2d82ee0dd931b7dfd2c93074d41202 Mon Sep 17 00:00:00 2001 From: stephenmk Date: Fri, 22 Dec 2023 12:11:15 -0600 Subject: [PATCH 3/3] Update test script with new media file count --- test/database.test.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/database.test.js b/test/database.test.js index 702de9f862..86c69a41c9 100644 --- a/test/database.test.js +++ b/test/database.test.js @@ -163,7 +163,7 @@ async function testDatabase1() { counts: { kanji: {total: 2}, kanjiMeta: {total: 6, freq: 6}, - media: {total: 4}, + media: {total: 6}, tagMeta: {total: 15}, termMeta: {total: 38, freq: 31, pitch: 7}, terms: {total: 21} @@ -193,13 +193,13 @@ async function testDatabase1() { true ); expect(counts).toStrictEqual({ - counts: [{kanji: 2, kanjiMeta: 6, terms: 21, termMeta: 38, tagMeta: 15, media: 4}], - total: {kanji: 2, kanjiMeta: 6, terms: 21, termMeta: 38, tagMeta: 15, media: 4} + counts: [{kanji: 2, kanjiMeta: 6, terms: 21, termMeta: 38, tagMeta: 15, media: 6}], + total: {kanji: 2, kanjiMeta: 6, terms: 21, termMeta: 38, tagMeta: 15, media: 6} }); // Test find* functions await testFindTermsBulkTest1(dictionaryDatabase, titles); - await testTindTermsExactBulk1(dictionaryDatabase, titles); + await testFindTermsExactBulk1(dictionaryDatabase, titles); await testFindTermsBySequenceBulk1(dictionaryDatabase, title); await testFindTermMetaBulk1(dictionaryDatabase, titles); await testFindKanjiBulk1(dictionaryDatabase, titles); @@ -335,8 +335,8 @@ async function testFindTermsBulkTest1(database, titles) { * @param {DictionaryDatabase} database * @param {import('dictionary-database').DictionarySet} titles */ -async function testTindTermsExactBulk1(database, titles) { - test('TindTermsExactBulk1', async () => { +async function testFindTermsExactBulk1(database, titles) { + test('FindTermsExactBulk1', async () => { /** @type {{inputs: {termList: {term: string, reading: string}[]}[], expectedResults: {total: number, terms: [key: string, count: number][], readings: [key: string, count: number][]}}[]} */ const data = [ {