Skip to content

Commit 478d38a

Browse files
committed
Improve Anki styles for gloss-sc-li
1 parent ef98bea commit 478d38a

5 files changed

Lines changed: 120 additions & 3 deletions

File tree

MaruAnkiTests/GlossaryHTMLFormatTests.swift

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ struct GlossaryHTMLFormatTests {
3434
term: String = "映像",
3535
reading: String? = "えいぞう",
3636
dictionaryTitle: String = "Dictionary A",
37-
dictionaryUUID: UUID = UUID()
37+
dictionaryUUID: UUID = UUID(),
38+
definitions: [Definition] = [.text("Test definition")]
3839
) -> SearchResult {
3940
let candidate = LookupCandidate(from: term)
4041
let rankingCriteria = RankingCriteria(
@@ -55,7 +56,7 @@ struct GlossaryHTMLFormatTests {
5556
candidate: candidate,
5657
term: term,
5758
reading: reading,
58-
definitions: [.text("Test definition")],
59+
definitions: definitions,
5960
frequency: nil,
6061
frequencies: [],
6162
pitchAccents: [],
@@ -196,6 +197,80 @@ struct GlossaryHTMLFormatTests {
196197
#expect(html.contains("<li data-dictionary="), "Missing li with data-dictionary")
197198
}
198199

200+
@Test("Single dictionary glossary preserves Jitendex sense lists", .bug("https://github.com/classicsc/MaruReader/issues/26"))
201+
func singleDictionaryGlossary_preservesJitendexSenseList() async throws {
202+
let dictionaryUUID = UUID()
203+
let definitionJSON = #"""
204+
{
205+
"type": "structured-content",
206+
"content": {
207+
"tag": "ul",
208+
"data": {"content": "sense-groups"},
209+
"content": {
210+
"tag": "li",
211+
"data": {"content": "sense-group"},
212+
"content": [
213+
{
214+
"tag": "span",
215+
"data": {"class": "tag", "content": "part-of-speech-info"},
216+
"content": "noun"
217+
},
218+
{
219+
"tag": "ol",
220+
"content": {
221+
"tag": "li",
222+
"style": {"listStyleType": "\"①\""},
223+
"data": {"content": "sense"},
224+
"content": {
225+
"tag": "ul",
226+
"data": {"content": "glossary"},
227+
"content": [
228+
{"tag": "li", "content": "major recession"},
229+
{"tag": "li", "content": "serious depression"}
230+
]
231+
}
232+
}
233+
}
234+
]
235+
}
236+
}
237+
}
238+
"""#
239+
let definition = try JSONDecoder().decode(Definition.self, from: Data(definitionJSON.utf8))
240+
let result = makeTestSearchResult(
241+
term: "大不況",
242+
reading: "だいふきょう",
243+
dictionaryTitle: "Jitendex",
244+
dictionaryUUID: dictionaryUUID,
245+
definitions: [definition]
246+
)
247+
let dictionaryResults = makeDictionaryResults(
248+
dictionaryTitle: "Jitendex",
249+
dictionaryUUID: dictionaryUUID,
250+
searchResults: [result]
251+
)
252+
let group = makeGroupedSearchResults(
253+
expression: "大不況",
254+
reading: "だいふきょう",
255+
dictionariesResults: [dictionaryResults]
256+
)
257+
let response = makeTextLookupResponse(selectedGroup: group)
258+
let resolver = TextLookupResponseTemplateResolver(
259+
response: response,
260+
selectedGroup: group,
261+
selectedDictionaryID: dictionaryUUID
262+
)
263+
264+
let resolved = await resolver.resolve(.singleDictionaryGlossary(dictionaryID: dictionaryUUID))
265+
let html = try #require(resolved.text)
266+
267+
#expect(html.contains("<ol><li data-dictionary=\"Jitendex\">"))
268+
#expect(html.contains("<ul style=\"margin: 0; padding-left: 1.5em; list-style-type: circle;\">"))
269+
#expect(html.contains("<ol class=\"gloss-sc-ol\">"))
270+
#expect(html.contains("list-style-type: &quot;①&quot;"))
271+
#expect(html.contains("data-sc-content=\"glossary\""))
272+
}
273+
199274
@Test func singleGlossary_usesFirstDisplayedDictionary() async {
200275
let firstDictionary = makeDictionaryResults(dictionaryTitle: "Dictionary A")
201276
let secondDictionary = makeDictionaryResults(dictionaryTitle: "Dictionary B")

MaruReaderCore/DictionarySearch/AnkiStyleProvider.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,23 @@ public enum AnkiStyleProvider {
295295
display: list-item;
296296
}
297297
298+
/* Compact glossary lists */
299+
.gloss-sc-ul[data-sc-content=glossary] {
300+
display: inline;
301+
list-style: none;
302+
padding-left: 0;
303+
}
304+
305+
.gloss-sc-ul[data-sc-content=glossary] .gloss-sc-li {
306+
display: inline;
307+
}
308+
309+
.gloss-sc-ul[data-sc-content=glossary] .gloss-sc-li:not(:first-child)::before {
310+
white-space: pre-wrap;
311+
content: ", ";
312+
display: inline;
313+
}
314+
298315
/* Link styles */
299316
.gloss-link {
300317
color: #0066cc;

MaruReaderCore/DictionaryTypes/Definition.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ extension [Definition] {
211211
let definitionHTML = definition.toAnkiHTML(mediaBaseURL: mediaBaseURL)
212212
return "<li style=\"margin: 0.25em 0;\" data-index=\"\(index)\">\(definitionHTML)</li>"
213213
}.joined()
214-
return "<ol style=\"margin: 0; padding-left: 1.5em; list-style-type: decimal;\">\(itemsHTML)</ol>"
214+
return "<ul style=\"margin: 0; padding-left: 1.5em; list-style-type: circle;\">\(itemsHTML)</ul>"
215215
}
216216

217217
/// Extracts all image paths from the definitions.

MaruReaderCoreTests/AnkiStyleProviderTests.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ struct AnkiStyleProviderTests {
7171
#expect(css.contains("padding-left: 2em"))
7272
}
7373

74+
@Test("Base styles compact structured glossary lists", .bug("https://github.com/classicsc/MaruReader/issues/26"))
75+
func baseStylesCSS_containsCompactGlossaryListStyles() {
76+
let css = AnkiStyleProvider.baseStylesCSS()
77+
78+
#expect(css.contains(".gloss-sc-ul[data-sc-content=glossary]"))
79+
#expect(css.contains(".gloss-sc-ul[data-sc-content=glossary] .gloss-sc-li"))
80+
#expect(css.contains("display: inline"))
81+
#expect(css.contains("list-style: none"))
82+
#expect(css.contains("content: \", \""))
83+
}
84+
7485
@Test func baseStylesCSS_containsLinkStyles() {
7586
let css = AnkiStyleProvider.baseStylesCSS()
7687

MaruReaderCoreTests/DefinitionHTMLGenerationTests.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,20 @@ struct DefinitionHTMLGenerationTests {
175175
#expect(html.contains("<ul class=\"gloss-glossary-list\""))
176176
}
177177

178+
@Test("Anki definitions use an unordered circle list", .bug("https://github.com/classicsc/MaruReader/issues/26"))
179+
func arrayOfDefinitions_toAnkiHTML_usesCircleList() {
180+
let definitions: [Definition] = [
181+
.text("First definition"),
182+
.text("Second definition"),
183+
]
184+
185+
let html = definitions.toAnkiHTML()
186+
187+
#expect(html.hasPrefix("<ul style=\"margin: 0; padding-left: 1.5em; list-style-type: circle;\">"))
188+
#expect(html.contains("list-style-type: decimal") == false)
189+
#expect(html.hasSuffix("</ul>"))
190+
}
191+
178192
@Test func imageDefinition_toHTML_rendersDescriptionWrapper() {
179193
let image = ImageDef(
180194
type: "image",

0 commit comments

Comments
 (0)