Skip to content

Commit a4cd54e

Browse files
committed
refactor
1 parent d1cfcc8 commit a4cd54e

8 files changed

Lines changed: 193 additions & 86 deletions

File tree

src-tauri/src/lib.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@ struct Kanji {
1616
nanori: String,
1717
}
1818

19+
#[derive(Serialize)]
20+
struct KanjiLookup {
21+
character: String,
22+
stroke_count: i32,
23+
grade: i32,
24+
jlpt_level: i32,
25+
frequency: i32,
26+
onyomi: String,
27+
kunyomi: String,
28+
meanings: Vec<String>,
29+
nanori: Vec<String>,
30+
}
31+
1932
#[command]
2033
fn get_all_kanji(app: AppHandle) -> Result<Vec<Kanji>, String> {
2134
println!("Fetching all kanji from database");
@@ -73,7 +86,7 @@ fn get_all_kanji(app: AppHandle) -> Result<Vec<Kanji>, String> {
7386
}
7487

7588
#[command]
76-
fn get_kanji(character: String, app: AppHandle) -> Result<Kanji, String> {
89+
fn get_kanji(character: String, app: AppHandle) -> Result<KanjiLookup, String> {
7790
println!("Searching for kanji: {}", character);
7891

7992
// Find the correct path to the bundled resource
@@ -102,16 +115,33 @@ fn get_kanji(character: String, app: AppHandle) -> Result<Kanji, String> {
102115

103116
let kanji = stmt
104117
.query_row([character], |row| {
105-
Ok(Kanji {
118+
let meanings_str: String = row.get::<_, String>(7).unwrap_or_default();
119+
let nanori_str: String = row.get::<_, String>(8).unwrap_or_default();
120+
121+
// Split meanings by semicolon and filter out empty strings
122+
let meanings: Vec<String> = meanings_str
123+
.split(';')
124+
.map(|s| s.trim().to_string())
125+
.filter(|s| !s.is_empty())
126+
.collect();
127+
128+
// Split nanori by comma and filter out empty strings
129+
let nanori: Vec<String> = nanori_str
130+
.split(',')
131+
.map(|s| s.trim().to_string())
132+
.filter(|s| !s.is_empty())
133+
.collect();
134+
135+
Ok(KanjiLookup {
106136
character: row.get(0)?,
107137
stroke_count: row.get(1)?,
108138
grade: row.get(2)?,
109139
jlpt_level: row.get(3)?,
110140
frequency: row.get(4)?,
111141
onyomi: row.get::<_, String>(5).unwrap_or_default(),
112142
kunyomi: row.get::<_, String>(6).unwrap_or_default(),
113-
meanings: row.get::<_, String>(7).unwrap_or_default(),
114-
nanori: row.get::<_, String>(8).unwrap_or_default(),
143+
meanings,
144+
nanori,
115145
})
116146
})
117147
.map_err(|e| {

src/app.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
--shadow-color: rgba(0, 0, 0, 0.1);
1515
--toggle-bg: #cccccc;
1616
--accent-color: #396cd8;
17+
--link-color: #396cd8;
18+
--link-hover-color: #2952a3;
19+
--link-visited-color: #5a67d8;
1720
}
1821

1922
:root.dark {
@@ -31,6 +34,9 @@
3134
--shadow-color: rgba(0, 0, 0, 0.3);
3235
--toggle-bg: #555555;
3336
--accent-color: #5a8cff;
37+
--link-color: #6fa8ff;
38+
--link-hover-color: #8abbff;
39+
--link-visited-color: #9d7bff;
3440
}
3541

3642
body {

src/routes/kana_view/kana-view.css

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77
.home-button {
88
padding: 0.5rem 1rem;
99
font-size: 1rem;
10-
background-color: #f3f3f3;
11-
border: 1px solid #ccc;
10+
background-color: var(--button-bg, #f3f3f3);
11+
border: 1px solid var(--button-border, #ccc);
1212
border-radius: 6px;
1313
cursor: pointer;
14+
color: var(--text-color, #000);
1415
}
1516

1617
.home-button:hover {
17-
background-color: #e0e0e0;
18+
background-color: var(--button-hover-bg, #e0e0e0);
19+
color: var(--text-color, #000);
1820
}
1921

2022
.tab-container {
@@ -34,7 +36,7 @@
3436
.section-title {
3537
text-align: center;
3638
margin: 1rem 0;
37-
color: #666;
39+
color: var(--text-color, #000);
3840
}
3941

4042
.section-title h2 {
@@ -46,15 +48,17 @@
4648
button {
4749
padding: 0.5rem 1rem;
4850
font-size: 1rem;
49-
border: 2px solid #ccc;
50-
background: white;
51+
border: 2px solid var(--border-color, #ccc);
52+
background: var(--section-bg, white);
5153
cursor: pointer;
5254
border-radius: 6px;
5355
transition: background 0.2s;
56+
color: var(--text-color, #000);
5457
}
5558

5659
button:hover {
57-
background-color: #f0f0f0;
60+
background-color: var(--button-hover-bg, #f0f0f0);
61+
color: var(--text-color, #000);
5862
}
5963

6064
.active-tab {
@@ -85,7 +89,7 @@ button:hover {
8589
text-align: center;
8690
font-weight: bold;
8791
font-size: 1.1rem;
88-
color: #666;
92+
color: var(--text-muted, #666);
8993
padding: 0.5rem;
9094
min-width: 60px;
9195
flex: 1;
@@ -113,7 +117,7 @@ button:hover {
113117
text-align: center;
114118
font-weight: bold;
115119
font-size: 1.1rem;
116-
color: #666;
120+
color: var(--text-muted, #666);
117121
padding: 0.5rem;
118122
min-width: 60px;
119123
max-width: 60px;
@@ -138,19 +142,20 @@ button:hover {
138142
justify-content: center;
139143
text-align: center;
140144
padding: 0.5rem;
141-
border: 1px solid #ddd;
145+
border: 1px solid var(--border-color, #ddd);
142146
border-radius: 8px;
143147
cursor: pointer;
144-
background: #fff;
145-
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
148+
background: var(--section-bg, #fff);
149+
box-shadow: 0 1px 3px var(--shadow-color, rgba(0,0,0,0.1));
146150
transition: all 0.2s ease;
147151
min-height: 70px;
152+
color: var(--text-color, #000);
148153
}
149154

150155
.kana-button:hover {
151156
transform: scale(1.05);
152-
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
153-
background-color: #f8f9fa;
157+
box-shadow: 0 2px 6px var(--shadow-color, rgba(0,0,0,0.15));
158+
background-color: var(--button-hover-bg, #f8f9fa);
154159
}
155160

156161
.kana-char {
@@ -162,7 +167,7 @@ button:hover {
162167

163168
.romaji {
164169
font-size: 0.8rem;
165-
color: #666;
170+
color: var(--text-muted, #666);
166171
font-weight: normal;
167172
}
168173

Lines changed: 92 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
<script lang="ts">
22
import { invoke } from "@tauri-apps/api/core";
33
import { goto } from "$app/navigation";
4-
import './kanji-lookup.css';
4+
import "./kanji-lookup.css";
55
let submitted_kanji = "";
66
let character = "";
77
let stroke_count = "";
88
let grade = "";
99
let jlpt_level = "";
1010
let frequency = "";
11-
let onyomi = "";
12-
let kunyomi = "";
11+
let onyomi: string[] = [];
12+
let kunyomi: string[] = [];
1313
let meanings: string[] = [];
1414
let nanori: string[] = [];
1515
let kanji_svg: string = "";
@@ -19,7 +19,9 @@
1919
event.preventDefault();
2020
error = "";
2121
meanings = [];
22-
onyomi = kunyomi = jlpt_level = "";
22+
nanori = [];
23+
onyomi = [];
24+
kunyomi = [];
2325
kanji_svg = "";
2426
2527
try {
@@ -45,9 +47,23 @@
4547
grade = result.grade.toString();
4648
jlpt_level = result.jlpt_level.toString();
4749
frequency = result.frequency.toString();
48-
onyomi = result.onyomi;
49-
kunyomi = result.kunyomi;
50-
meanings = result.meanings;
50+
51+
// Split onyomi and kunyomi by comma and filter out empty strings
52+
onyomi = result.onyomi
53+
? result.onyomi
54+
.split(",")
55+
.map((s) => s.trim())
56+
.filter((s) => s.length > 0)
57+
: [];
58+
kunyomi = result.kunyomi
59+
? result.kunyomi
60+
.split(",")
61+
.map((s) => s.trim())
62+
.filter((s) => s.length > 0)
63+
: [];
64+
65+
// result.meanings is already an array, no need to split
66+
meanings = result.meanings || [];
5167
nanori = result.nanori;
5268
} catch (e) {
5369
console.log("Error fetching kanji data:", e);
@@ -60,47 +76,51 @@
6076
}
6177
6278
export function insertSvg(node: HTMLElement) {
63-
if (kanji_svg) {
64-
try {
65-
// Create a temporary container to parse the SVG string properly
66-
const parser = new DOMParser();
67-
const doc = parser.parseFromString(kanji_svg, "image/svg+xml");
68-
69-
// Extract just the SVG element
70-
const svgElement = doc.querySelector("svg");
71-
72-
if (svgElement) {
73-
// Clear the node and append the SVG element
74-
node.innerHTML = "";
75-
node.appendChild(svgElement.cloneNode(true));
76-
} else {
77-
console.error("No SVG element found in the string");
78-
}
79-
} catch (e) {
80-
console.error("Error parsing SVG:", e);
81-
82-
// Fallback to regex cleaning if parsing fails
83-
const cleaned = kanji_svg
84-
.replace(/<\?xml[^>]*\?>/g, '') // Remove XML declaration
85-
.replace(/<!DOCTYPE[^>]*>/g, '') // Remove DOCTYPE
86-
.replace(/<!ENTITY[^>]*>/g, '') // Remove ENTITY declarations
87-
.replace(/<!\[CDATA\[.*?\]\]>/gs, '') // Remove CDATA sections
88-
.replace(/\]\s*>$/g, '') // Remove trailing ]>
89-
.replace(/\s*\]\s*>$/g, ''); // Remove trailing ]> with whitespace
90-
91-
const svgStart = cleaned.indexOf("<svg");
92-
const svgEnd = cleaned.lastIndexOf("</svg>") + 6; // +6 for "</svg>"
93-
94-
if (svgStart >= 0 && svgEnd > svgStart) {
95-
node.innerHTML = cleaned.substring(svgStart, svgEnd);
96-
} else {
97-
node.innerHTML = cleaned;
79+
if (kanji_svg) {
80+
try {
81+
// Create a temporary container to parse the SVG string properly
82+
const parser = new DOMParser();
83+
const doc = parser.parseFromString(kanji_svg, "image/svg+xml");
84+
85+
// Extract just the SVG element
86+
const svgElement = doc.querySelector("svg");
87+
88+
if (svgElement) {
89+
// Clear the node and append the SVG element
90+
node.innerHTML = "";
91+
node.appendChild(svgElement.cloneNode(true));
92+
} else {
93+
console.error("No SVG element found in the string");
94+
}
95+
} catch (e) {
96+
console.error("Error parsing SVG:", e);
97+
98+
// Fallback to regex cleaning if parsing fails
99+
const cleaned = kanji_svg
100+
.replace(/<\?xml[^>]*\?>/g, "") // Remove XML declaration
101+
.replace(/<!DOCTYPE[^>]*>/g, "") // Remove DOCTYPE
102+
.replace(/<!ENTITY[^>]*>/g, "") // Remove ENTITY declarations
103+
.replace(/<!\[CDATA\[.*?\]\]>/gs, "") // Remove CDATA sections
104+
.replace(/\]\s*>$/g, "") // Remove trailing ]>
105+
.replace(/\s*\]\s*>$/g, ""); // Remove trailing ]> with whitespace
106+
107+
const svgStart = cleaned.indexOf("<svg");
108+
const svgEnd = cleaned.lastIndexOf("</svg>") + 6; // +6 for "</svg>"
109+
110+
if (svgStart >= 0 && svgEnd > svgStart) {
111+
node.innerHTML = cleaned.substring(svgStart, svgEnd);
112+
} else {
113+
node.innerHTML = cleaned;
114+
}
98115
}
99116
}
100117
}
101-
}
102118
</script>
103119

120+
<div class="nav-bar">
121+
<button class="home-button" on:click={goToHome}>Back to Home</button>
122+
</div>
123+
104124
<main class="container">
105125
<h1>Kanji Lookup</h1>
106126

@@ -113,8 +133,6 @@
113133
<button type="submit">Search</button>
114134
</form>
115135

116-
<button class="home-button" on:click={goToHome}> Back to Home </button>
117-
118136
{#if error}
119137
<p style="color: red;">{error}</p>
120138
{:else if meanings.length > 0}
@@ -124,23 +142,43 @@
124142
<p><strong>Grade: {grade}</strong></p>
125143
<p><strong>JLPT Level: {jlpt_level}</strong></p>
126144
<p><strong>Frequency: {frequency}</strong></p>
127-
<p><strong>Onyomi: {onyomi}</strong></p>
128-
<p><strong>Kunyomi: {kunyomi}</strong></p>
145+
146+
{#if onyomi.length > 0}
147+
<p><strong>Onyomi:</strong></p>
148+
<ul>
149+
{#each onyomi as reading}
150+
<li>{reading}</li>
151+
{/each}
152+
</ul>
153+
{/if}
154+
155+
{#if kunyomi.length > 0}
156+
<p><strong>Kunyomi:</strong></p>
157+
<ul>
158+
{#each kunyomi as reading}
159+
<li>{reading}</li>
160+
{/each}
161+
</ul>
162+
{/if}
163+
129164
<p><strong>Meanings:</strong></p>
130165
<ul>
131166
{#each meanings as meaning}
132167
<li>{meaning}</li>
133168
{/each}
134169
</ul>
135-
<p><strong>Nanori:</strong></p>
136-
<ul>
137-
{#each nanori as name}
138-
<li>{name}</li>
139-
{/each}
140-
</ul>
170+
171+
{#if nanori.length > 0}
172+
<p><strong>Nanori:</strong></p>
173+
<ul>
174+
{#each nanori as name}
175+
<li>{name}</li>
176+
{/each}
177+
</ul>
178+
{/if}
141179
{#if kanji_svg}
142180
<div class="svg-container" use:insertSvg></div>
143181
{/if}
144182
</div>
145183
{/if}
146-
</main>
184+
</main>

0 commit comments

Comments
 (0)