feat: use version meta

fixes #150
This commit is contained in:
2025-02-13 16:16:33 +01:00
parent 4d73dad780
commit 7ca9e04dd3
20 changed files with 349 additions and 648 deletions

View File

@@ -1,497 +0,0 @@
s + Dup,say
y + b,by
y + Dup,why
n + Dup,no
n + f,find
l + f,life
l + p,people
l + s + p,spell
l + n,line
l + n + p,plant
t + h,that
t + n + h,than
t + n + p,plant
t + l + f,left
a + f,after
a + d,add
a + d + f,had
a + h,has
a + s,as
a + s + h,has
a + y + d,day
a + y + s,say
a + n,an
a + n + d,and
a + n + d + f,hand
a + n + h,hand
a + n + y,any
a + l,all
a + l + d,land
a + l + p,plant
a + l + s,last
a + l + y + p,play
a + l + n + d,land
a + t,at
a + t + h,that
a + t + n + h,than
a + t + l + s,last
a + t + l + n + p,plant
- + ?,question
w + h,who
w + s,saw
w + y + h,why
w + t,without
w + t + h,watch
w + t + n,went
w + a,was
w + a + h,what
w + a + s,saw
w + a + y,way
w + a + y + Dup,away
w + a + n,want
w + a + l + f,walk
w + a + l + y,always
w + a + l + y + s,always
w + a + t,watch
w + a + t + h,watch
w + a + t + n,want
g + b,begin
g + Dup,question
g + h,here
g + p,page
g + l + n,long
g + t,get
k + q,quick
k + f,and
k + l + y + q,quickly
k + t + l,talk
k + a + b,back
k + a + s,ask
k + a + t + l,talk
k + w + a + l,walk
m + f,form
m + y,my
m + t + Dup,mountain
m + a + f,family
m + a + s,small
m + a + y,may
m + a + n,man
m + a + n + y,many
m + a + l,almost
m + a + l + s,small
m + a + l + s + Dup,small
c + b,because
c + Dup,sea
c + h,head
c + a + n,can
c + a + n + h,change
c + a + l,call
c + a + l + p,place
c + k + a + b,back
u + p,us
u + y,you
u + j,just
u + j + s,just
u + t + b,but
u + t + p,put
u + t + s + d,study
u + t + n,until
u + t + j + s,just
u + a + l,last
u + k + q,quick
u + k + l + y + q,quickly
u + m + h,much
u + m + n,number
u + m + t + s,must
u + m + c + h,much
u + c + s + h,such
u + c + t,cut
u + c + t + n,country
' + a + s,say
' + a + n,any
' + m + a + n,many
o + Dup,off
o + f,of
o + f + f,food
o + d,do
o + s,so
o + y + b,boy
o + n,on
o + n + s + Dup,soon
o + l,line
o + l + Dup,oil
o + l + d,old
o + l + y,only
o + l + n + y,only
o + t,to
o + t + b,both
o + t + Dup,too
o + t + s,stop
o + t + s + p,stop
o + t + n,not
o + t + n + f,often
o + t + n + d,don't
o + t + n + p,point
o + a + n + h,another
o + a + l,also
o + a + l + s,also
o + w,own
o + w + h,how
o + w + s + h,show
o + w + n,now
o + w + n + d,down
o + w + l + f,follow
o + w + t,two
o + g,go
o + g + Dup,good
o + g + n + s,song
o + g + l + n,long
o + g + t,got
o + g + a + l,along
o + g + a + l + n,along
o + k + b,book
o + k + n,know
o + k + l,look
o + k + t,took
o + k + t + Dup,took
o + k + w + n,know
o + v + a + b,above
o + v + k,move
o + m + s,some
o + m + t + s,most
o + m + a + l,almost
o + m + a + l + s,almost
o + m + a + t + l + s,almost
o + c + f,food
o + c + l + s + h,school
o + u,our
o + u + f,four
o + u + s + h,should
o + u + y,you
o + u + n + f,found
o + u + n + f + f,found
o + u + n + s,sound
o + u + n + s + d,sound
o + u + l + s + d + f,should
o + u + l + s + h,should
o + u + t,out
o + u + a + b,about
o + u + a + t + b,about
o + u + w + l + d,would
o + u + g + n + y,young
o + u + g + t + h,thought
o + u + m + t + n,mountain
o + u + m + t + n + Dup,mountain
o + u + c + l + d,could
o + ' + t + n + d,don't
o + o + l,oil
o + o + t + n,into
o + o + t + n + p,point
o + o + u + w + t + h,without
o + o + u + m + a + t + n,mountain
i + f,if
i + f + f,different
i + d,did
i + RH_Thumb_1_Center,different
i + s,is
i + s + d,side
i + s + h,his
i + n,in
i + n + f + f,find
i + l,list
i + l + n,line
i + t,it
i + t + s + Dup,still
i + t + s + h,this
i + t + n,into
i + t + l + s,list
i + t + l + s + Dup,still
i + a + s,said
i + a + s + d,said
i + a + n,animal
i + w + h,which
i + w + h + Dup,which
i + w + l,will
i + w + l + Dup,will
i + w + l + h,while
i + w + t + h,with
i + g,give
i + g + b,big
i + g + h,high
i + g + n + h,night
i + g + l + h,light
i + g + t + n + h,thing
i + g + t + l + h,light
i + g + a + n,again
i + g + a + n + Dup,again
i + k + n + d,kind
i + k + l,like
i + k + t + n + h,think
i + v + l,live
i + m + h,him
i + m + p,important
i + m + s,miss
i + m + s + Dup,miss
i + m + l,mile
i + m + t,time
i + m + t + h,might
i + m + a + n,animal
i + m + a + n + Dup,animal
i + m + a + l + n,another
i + m + g + t + h,might
i + c + p,picture
i + c + t + y,city
i + u + t + l + n,until
i + u + w + t + h,without
i + u + k + q,quick
i + u + k + l + y + q,quickly
i + u + c + k + q,quick
i + u + c + k + l + y + q,quickly
i + ' + t,it's
i + ' + t + s,it's
e + b,be
e + Dup,earth
e + x,example
e + f + b,before
e + h,he
e + h + Dup,here
e + s,state
e + s + Dup,see
e + s + h,she
e + y + Dup,eye
e + n,name
e + n + b,been
e + n + Dup,need
e + n + d,end
e + l + h,help
e + l + h + f,help
e + l + s + p,spell
e + t,the
e + t + Dup,eat
e + t + f,feet
e + t + h,there
e + t + s,set
e + t + s + h,these
e + t + y + h,they
e + t + n + x,next
e + t + n + h,then
e + t + l,let
e + t + l + Dup,tell
e + t + l + f,left
e + a,at
e + a + f,father
e + a + d + f,head
e + a + h,hear
e + a + p,paper
e + a + s,sea
e + a + y,year
e + a + n,name
e + a + t,eat
e + a + t + s + Dup,state
e + w,we
e + w + f,few
e + w + n,new
e + w + n + h,when
e + w + l,well
e + w + l + Dup,well
e + w + t + b,between
e + w + t + n,went
e + w + t + n + b,between
e + g + h,here
e + g + t,get
e + g + a + p,page
e + g + a + n + b,began
e + k,keep
e + k + p,keep
e + k + t,take
e + k + a + t,take
e + v + y,every
e + v + n,even
e + v + a + h,have
e + v + a + l,leave
e + v + a + l + Dup,leave
e + m,me
e + m + s,seem
e + m + s + Dup,seem
e + m + n,men
e + m + t + h,them
e + m + a,make
e + m + a + d,made
e + m + a + s,same
e + m + a + n,mean
e + m + a + l + p + x,example
e + m + c + a,came
e + c + s,second
e + c + t + n + s,sentence
e + c + a,came
e + c + a + f,face
e + c + a + h,each
e + c + a + l + p,place
e + LH_Thumb_1_Center + a,make
e + u + s,use
e + u + s + q,question
e + u + n + d,under
e + u + t + q,quite
e + u + c + a + s + b,because
e + o + p,open
e + o + s + d,does
e + o + n,one
e + o + n + p,open
e + o + l + b,below
e + o + l + h,hello
e + o + l + h + Dup,hello
e + o + l + p,people
e + o + t + f,often
e + o + t + h,other
e + o + t + s + h,those
e + o + t + n + f,often
e + o + w + l + b,below
e + o + g + t + h,together
e + o + v,over
e + o + v + a + b,above
e + o + v + k,move
e + o + m,move
e + o + m + h,home
e + o + m + s,some
e + o + m + t + s,sometime
e + o + m + t + s + h,something
e + o + m + g + t + n + s + h,something
e + o + m + c,come
e + o + c,come
e + o + c + n,once
e + o + c + n + s + d,second
e + o + c + l + s,close
e + o + u + s + h,house
e + o + u + n,enough
e + o + u + g + n + h,enough
e + i + s + d,side
e + i + l + f,life
e + i + l + n,line
e + i + t + q,quite
e + i + t + l,little
e + i + t + l + Dup,little
e + i + a + d,idea
e + i + w + l + h,while
e + i + w + t + h,white
e + i + g,give
e + i + g + p,give
e + i + g + n + b,begin
e + i + k + l,like
e + i + v + l,live
e + i + m + l,mile
e + i + m + t,time
e + i + u + t + q,quite
e + i + u + u + t + n + s + q,question
r + e + h,her
r + e + t + Dup,tree
r + e + t + h,there
r + e + t + h + Dup,three
r + e + t + l,letter
r + e + a,are
r + e + a + d,read
r + e + a + h,hear
r + e + a + p,paper
r + e + a + n,near
r + e + a + l + y,really
r + e + a + l + y + Dup,really
r + e + a + t + f,after
r + e + a + t + h,earth
r + e + a + t + RH_Thumb_1_Center,father
r + e + a + t + l,learn
r + e + w,were
r + e + w + Dup,were
r + e + w + h,where
r + e + w + a + n + s,answer
r + e + w + a + t,water
r + e + g + h,here
r + e + g + a + l,large
r + e + g + a + t,great
r + e + v + y,very
r + e + v + y + Dup,every
r + e + v + n,never
r + e + u + n + d,under
r + e + u + m + n + b,number
r + e + o + f + b,before
r + e + o + t + h,other
r + e + o + g + t + h,together
r + e + o + v,over
r + e + o + m,more
r + e + o + m + t + h,mother
r + e + i + t + h,their
r + e + i + t + n + f + f,different
r + e + i + v,river
r + e + i + c + l + d + f,children
r + e + i + u + c + t + p,picture
r + f,for
r + h,her
r + y,your
r + n,near
r + l,learn
r + t + Dup,tree
r + t + f,father
r + t + s + Dup,start
r + t + y,try
r + t + l,letter
r + t + l + Dup,letter
r + a,are
r + a + f,far
r + a + d,read
r + a + d + f,hard
r + a + h,hard
r + a + p,part
r + a + l + y,really
r + a + l + y + Dup,really
r + a + t + p,part
r + a + t + s + Dup,start
r + w,were
r + w + h,where
r + w + t,water
r + w + a + n + s,answer
r + g + t,great
r + g + a + l,large
r + v + y,very
r + v + n,never
r + v + l,later
r + m + f,form
r + c + a,car
r + c + a + y,carry
r + c + a + y + Dup,carry
r + u + n,run
r + u + t + h,through
r + u + t + n,turn
r + ' + t + s,story
r + o,or
r + o + f,for
r + o + t + y + s,story
r + o + a + n + h,another
r + o + w,work
r + o + w + d,word
r + o + w + l + d,world
r + o + g,grow
r + o + LeftDoubleClick,grow
r + o + k + w,work
r + o + m,more
r + o + m + f,from
r + o + m + t + h,mother
r + o + u,our
r + o + u + f,four
r + o + u + y,your
r + o + u + a,around
r + o + u + a + n,around
r + o + u + a + n + d,around
r + o + u + g,group
r + o + u + g + p,group
r + o + u + g + t + h,through
r + o + u + c + t + n,country
r + o + u + c + t + n + y,country
r + i + t + h,their
r + i + t + s + f,first
r + i + a,air
r + i + w + t,write
r + i + g + h,right
r + i + g + l,girl
r + i + g + t + h,right
r + i + v,river
r + i + v + Dup,river
r + i + m + t + n + p,important
r + i + c + l + h,children
1 s + Dup say
2 y + b by
3 y + Dup why
4 n + Dup no
5 n + f find
6 l + f life
7 l + p people
8 l + s + p spell
9 l + n line
10 l + n + p plant
11 t + h that
12 t + n + h than
13 t + n + p plant
14 t + l + f left
15 a + f after
16 a + d add
17 a + d + f had
18 a + h has
19 a + s as
20 a + s + h has
21 a + y + d day
22 a + y + s say
23 a + n an
24 a + n + d and
25 a + n + d + f hand
26 a + n + h hand
27 a + n + y any
28 a + l all
29 a + l + d land
30 a + l + p plant
31 a + l + s last
32 a + l + y + p play
33 a + l + n + d land
34 a + t at
35 a + t + h that
36 a + t + n + h than
37 a + t + l + s last
38 a + t + l + n + p plant
39 - + ? question
40 w + h who
41 w + s saw
42 w + y + h why
43 w + t without
44 w + t + h watch
45 w + t + n went
46 w + a was
47 w + a + h what
48 w + a + s saw
49 w + a + y way
50 w + a + y + Dup away
51 w + a + n want
52 w + a + l + f walk
53 w + a + l + y always
54 w + a + l + y + s always
55 w + a + t watch
56 w + a + t + h watch
57 w + a + t + n want
58 g + b begin
59 g + Dup question
60 g + h here
61 g + p page
62 g + l + n long
63 g + t get
64 k + q quick
65 k + f and
66 k + l + y + q quickly
67 k + t + l talk
68 k + a + b back
69 k + a + s ask
70 k + a + t + l talk
71 k + w + a + l walk
72 m + f form
73 m + y my
74 m + t + Dup mountain
75 m + a + f family
76 m + a + s small
77 m + a + y may
78 m + a + n man
79 m + a + n + y many
80 m + a + l almost
81 m + a + l + s small
82 m + a + l + s + Dup small
83 c + b because
84 c + Dup sea
85 c + h head
86 c + a + n can
87 c + a + n + h change
88 c + a + l call
89 c + a + l + p place
90 c + k + a + b back
91 u + p us
92 u + y you
93 u + j just
94 u + j + s just
95 u + t + b but
96 u + t + p put
97 u + t + s + d study
98 u + t + n until
99 u + t + j + s just
100 u + a + l last
101 u + k + q quick
102 u + k + l + y + q quickly
103 u + m + h much
104 u + m + n number
105 u + m + t + s must
106 u + m + c + h much
107 u + c + s + h such
108 u + c + t cut
109 u + c + t + n country
110 ' + a + s say
111 ' + a + n any
112 ' + m + a + n many
113 o + Dup off
114 o + f of
115 o + f + f food
116 o + d do
117 o + s so
118 o + y + b boy
119 o + n on
120 o + n + s + Dup soon
121 o + l line
122 o + l + Dup oil
123 o + l + d old
124 o + l + y only
125 o + l + n + y only
126 o + t to
127 o + t + b both
128 o + t + Dup too
129 o + t + s stop
130 o + t + s + p stop
131 o + t + n not
132 o + t + n + f often
133 o + t + n + d don't
134 o + t + n + p point
135 o + a + n + h another
136 o + a + l also
137 o + a + l + s also
138 o + w own
139 o + w + h how
140 o + w + s + h show
141 o + w + n now
142 o + w + n + d down
143 o + w + l + f follow
144 o + w + t two
145 o + g go
146 o + g + Dup good
147 o + g + n + s song
148 o + g + l + n long
149 o + g + t got
150 o + g + a + l along
151 o + g + a + l + n along
152 o + k + b book
153 o + k + n know
154 o + k + l look
155 o + k + t took
156 o + k + t + Dup took
157 o + k + w + n know
158 o + v + a + b above
159 o + v + k move
160 o + m + s some
161 o + m + t + s most
162 o + m + a + l almost
163 o + m + a + l + s almost
164 o + m + a + t + l + s almost
165 o + c + f food
166 o + c + l + s + h school
167 o + u our
168 o + u + f four
169 o + u + s + h should
170 o + u + y you
171 o + u + n + f found
172 o + u + n + f + f found
173 o + u + n + s sound
174 o + u + n + s + d sound
175 o + u + l + s + d + f should
176 o + u + l + s + h should
177 o + u + t out
178 o + u + a + b about
179 o + u + a + t + b about
180 o + u + w + l + d would
181 o + u + g + n + y young
182 o + u + g + t + h thought
183 o + u + m + t + n mountain
184 o + u + m + t + n + Dup mountain
185 o + u + c + l + d could
186 o + ' + t + n + d don't
187 o + o + l oil
188 o + o + t + n into
189 o + o + t + n + p point
190 o + o + u + w + t + h without
191 o + o + u + m + a + t + n mountain
192 i + f if
193 i + f + f different
194 i + d did
195 i + RH_Thumb_1_Center different
196 i + s is
197 i + s + d side
198 i + s + h his
199 i + n in
200 i + n + f + f find
201 i + l list
202 i + l + n line
203 i + t it
204 i + t + s + Dup still
205 i + t + s + h this
206 i + t + n into
207 i + t + l + s list
208 i + t + l + s + Dup still
209 i + a + s said
210 i + a + s + d said
211 i + a + n animal
212 i + w + h which
213 i + w + h + Dup which
214 i + w + l will
215 i + w + l + Dup will
216 i + w + l + h while
217 i + w + t + h with
218 i + g give
219 i + g + b big
220 i + g + h high
221 i + g + n + h night
222 i + g + l + h light
223 i + g + t + n + h thing
224 i + g + t + l + h light
225 i + g + a + n again
226 i + g + a + n + Dup again
227 i + k + n + d kind
228 i + k + l like
229 i + k + t + n + h think
230 i + v + l live
231 i + m + h him
232 i + m + p important
233 i + m + s miss
234 i + m + s + Dup miss
235 i + m + l mile
236 i + m + t time
237 i + m + t + h might
238 i + m + a + n animal
239 i + m + a + n + Dup animal
240 i + m + a + l + n another
241 i + m + g + t + h might
242 i + c + p picture
243 i + c + t + y city
244 i + u + t + l + n until
245 i + u + w + t + h without
246 i + u + k + q quick
247 i + u + k + l + y + q quickly
248 i + u + c + k + q quick
249 i + u + c + k + l + y + q quickly
250 i + ' + t it's
251 i + ' + t + s it's
252 e + b be
253 e + Dup earth
254 e + x example
255 e + f + b before
256 e + h he
257 e + h + Dup here
258 e + s state
259 e + s + Dup see
260 e + s + h she
261 e + y + Dup eye
262 e + n name
263 e + n + b been
264 e + n + Dup need
265 e + n + d end
266 e + l + h help
267 e + l + h + f help
268 e + l + s + p spell
269 e + t the
270 e + t + Dup eat
271 e + t + f feet
272 e + t + h there
273 e + t + s set
274 e + t + s + h these
275 e + t + y + h they
276 e + t + n + x next
277 e + t + n + h then
278 e + t + l let
279 e + t + l + Dup tell
280 e + t + l + f left
281 e + a at
282 e + a + f father
283 e + a + d + f head
284 e + a + h hear
285 e + a + p paper
286 e + a + s sea
287 e + a + y year
288 e + a + n name
289 e + a + t eat
290 e + a + t + s + Dup state
291 e + w we
292 e + w + f few
293 e + w + n new
294 e + w + n + h when
295 e + w + l well
296 e + w + l + Dup well
297 e + w + t + b between
298 e + w + t + n went
299 e + w + t + n + b between
300 e + g + h here
301 e + g + t get
302 e + g + a + p page
303 e + g + a + n + b began
304 e + k keep
305 e + k + p keep
306 e + k + t take
307 e + k + a + t take
308 e + v + y every
309 e + v + n even
310 e + v + a + h have
311 e + v + a + l leave
312 e + v + a + l + Dup leave
313 e + m me
314 e + m + s seem
315 e + m + s + Dup seem
316 e + m + n men
317 e + m + t + h them
318 e + m + a make
319 e + m + a + d made
320 e + m + a + s same
321 e + m + a + n mean
322 e + m + a + l + p + x example
323 e + m + c + a came
324 e + c + s second
325 e + c + t + n + s sentence
326 e + c + a came
327 e + c + a + f face
328 e + c + a + h each
329 e + c + a + l + p place
330 e + LH_Thumb_1_Center + a make
331 e + u + s use
332 e + u + s + q question
333 e + u + n + d under
334 e + u + t + q quite
335 e + u + c + a + s + b because
336 e + o + p open
337 e + o + s + d does
338 e + o + n one
339 e + o + n + p open
340 e + o + l + b below
341 e + o + l + h hello
342 e + o + l + h + Dup hello
343 e + o + l + p people
344 e + o + t + f often
345 e + o + t + h other
346 e + o + t + s + h those
347 e + o + t + n + f often
348 e + o + w + l + b below
349 e + o + g + t + h together
350 e + o + v over
351 e + o + v + a + b above
352 e + o + v + k move
353 e + o + m move
354 e + o + m + h home
355 e + o + m + s some
356 e + o + m + t + s sometime
357 e + o + m + t + s + h something
358 e + o + m + g + t + n + s + h something
359 e + o + m + c come
360 e + o + c come
361 e + o + c + n once
362 e + o + c + n + s + d second
363 e + o + c + l + s close
364 e + o + u + s + h house
365 e + o + u + n enough
366 e + o + u + g + n + h enough
367 e + i + s + d side
368 e + i + l + f life
369 e + i + l + n line
370 e + i + t + q quite
371 e + i + t + l little
372 e + i + t + l + Dup little
373 e + i + a + d idea
374 e + i + w + l + h while
375 e + i + w + t + h white
376 e + i + g give
377 e + i + g + p give
378 e + i + g + n + b begin
379 e + i + k + l like
380 e + i + v + l live
381 e + i + m + l mile
382 e + i + m + t time
383 e + i + u + t + q quite
384 e + i + u + u + t + n + s + q question
385 r + e + h her
386 r + e + t + Dup tree
387 r + e + t + h there
388 r + e + t + h + Dup three
389 r + e + t + l letter
390 r + e + a are
391 r + e + a + d read
392 r + e + a + h hear
393 r + e + a + p paper
394 r + e + a + n near
395 r + e + a + l + y really
396 r + e + a + l + y + Dup really
397 r + e + a + t + f after
398 r + e + a + t + h earth
399 r + e + a + t + RH_Thumb_1_Center father
400 r + e + a + t + l learn
401 r + e + w were
402 r + e + w + Dup were
403 r + e + w + h where
404 r + e + w + a + n + s answer
405 r + e + w + a + t water
406 r + e + g + h here
407 r + e + g + a + l large
408 r + e + g + a + t great
409 r + e + v + y very
410 r + e + v + y + Dup every
411 r + e + v + n never
412 r + e + u + n + d under
413 r + e + u + m + n + b number
414 r + e + o + f + b before
415 r + e + o + t + h other
416 r + e + o + g + t + h together
417 r + e + o + v over
418 r + e + o + m more
419 r + e + o + m + t + h mother
420 r + e + i + t + h their
421 r + e + i + t + n + f + f different
422 r + e + i + v river
423 r + e + i + c + l + d + f children
424 r + e + i + u + c + t + p picture
425 r + f for
426 r + h her
427 r + y your
428 r + n near
429 r + l learn
430 r + t + Dup tree
431 r + t + f father
432 r + t + s + Dup start
433 r + t + y try
434 r + t + l letter
435 r + t + l + Dup letter
436 r + a are
437 r + a + f far
438 r + a + d read
439 r + a + d + f hard
440 r + a + h hard
441 r + a + p part
442 r + a + l + y really
443 r + a + l + y + Dup really
444 r + a + t + p part
445 r + a + t + s + Dup start
446 r + w were
447 r + w + h where
448 r + w + t water
449 r + w + a + n + s answer
450 r + g + t great
451 r + g + a + l large
452 r + v + y very
453 r + v + n never
454 r + v + l later
455 r + m + f form
456 r + c + a car
457 r + c + a + y carry
458 r + c + a + y + Dup carry
459 r + u + n run
460 r + u + t + h through
461 r + u + t + n turn
462 r + ' + t + s story
463 r + o or
464 r + o + f for
465 r + o + t + y + s story
466 r + o + a + n + h another
467 r + o + w work
468 r + o + w + d word
469 r + o + w + l + d world
470 r + o + g grow
471 r + o + LeftDoubleClick grow
472 r + o + k + w work
473 r + o + m more
474 r + o + m + f from
475 r + o + m + t + h mother
476 r + o + u our
477 r + o + u + f four
478 r + o + u + y your
479 r + o + u + a around
480 r + o + u + a + n around
481 r + o + u + a + n + d around
482 r + o + u + g group
483 r + o + u + g + p group
484 r + o + u + g + t + h through
485 r + o + u + c + t + n country
486 r + o + u + c + t + n + y country
487 r + i + t + h their
488 r + i + t + s + f first
489 r + i + a air
490 r + i + w + t write
491 r + i + g + h right
492 r + i + g + l girl
493 r + i + g + t + h right
494 r + i + v river
495 r + i + v + Dup river
496 r + i + m + t + n + p important
497 r + i + c + l + h children

View File

@@ -11,7 +11,7 @@
let info = $derived( let info = $derived(
typeof action === "number" typeof action === "number"
? (KEYMAP_CODES.get(action) ?? { code: action }) ? ($KEYMAP_CODES.get(action) ?? { code: action })
: action, : action,
); );
let dynamicMapping = $derived(info.keyCode && $osLayout.get(info.keyCode)); let dynamicMapping = $derived(info.keyCode && $osLayout.get(info.keyCode));

View File

@@ -12,7 +12,7 @@
$props(); $props();
let key = $derived( let key = $derived(
(typeof id === "number" ? KEYMAP_CODES.get(id) ?? id : id) as (typeof id === "number" ? ($KEYMAP_CODES.get(id) ?? id) : id) as
| number | number
| KeyInfo, | KeyInfo,
); );

View File

@@ -3,12 +3,14 @@
KEYMAP_CATEGORIES, KEYMAP_CATEGORIES,
KEYMAP_CODES, KEYMAP_CODES,
KEYMAP_IDS, KEYMAP_IDS,
type KeyInfo,
} from "$lib/serial/keymap-codes"; } from "$lib/serial/keymap-codes";
import FlexSearch from "flexsearch"; import FlexSearch from "flexsearch";
import { onMount } from "svelte"; import { onMount } from "svelte";
import ActionListItem from "$lib/components/ActionListItem.svelte"; import ActionListItem from "$lib/components/ActionListItem.svelte";
import LL from "$i18n/i18n-svelte"; import LL from "$i18n/i18n-svelte";
import { action } from "$lib/title"; import { action } from "$lib/title";
import { get } from "svelte/store";
let { let {
currentAction = undefined, currentAction = undefined,
@@ -27,10 +29,13 @@
}); });
const index = new FlexSearch.Index({ tokenize: "full" }); const index = new FlexSearch.Index({ tokenize: "full" });
createIndex();
async function createIndex() { $effect(() => {
for (const [, action] of KEYMAP_CODES) { createIndex($KEYMAP_CODES);
});
async function createIndex(codes: Map<number, KeyInfo>) {
for (const [, action] of codes) {
await index?.addAsync( await index?.addAsync(
action.code, action.code,
`${action.title || ""} ${action.variant || ""} ${action.category} ${action.id || ""} ${ `${action.title || ""} ${action.variant || ""} ${action.category} ${action.id || ""} ${
@@ -42,7 +47,7 @@
async function search() { async function search() {
results = (await index!.searchAsync(searchBox.value)) as number[]; results = (await index!.searchAsync(searchBox.value)) as number[];
exact = KEYMAP_IDS.get(searchBox.value)?.code; exact = get(KEYMAP_IDS).get(searchBox.value)?.code;
code = Number(searchBox.value); code = Number(searchBox.value);
} }
@@ -127,7 +132,7 @@
bind:group={filter} bind:group={filter}
/></label /></label
> >
{#each KEYMAP_CATEGORIES as category} {#each $KEYMAP_CATEGORIES as category}
<label <label
>{category.name}<input >{category.name}<input
name="category" name="category"
@@ -167,7 +172,7 @@
{#if filter !== undefined || results.length > 0} {#if filter !== undefined || results.length > 0}
{@const resultValue = {@const resultValue =
results.length === 0 results.length === 0
? Array.from(KEYMAP_CODES, ([it]) => it) ? Array.from($KEYMAP_CODES, ([it]) => it)
: results} : results}
{#each filter ? resultValue.filter( (it) => filter.has(it), ) : resultValue as id (id)} {#each filter ? resultValue.filter( (it) => filter.has(it), ) : resultValue as id (id)}
<li><ActionListItem {id} onclick={() => select(id)} /></li> <li><ActionListItem {id} onclick={() => select(id)} /></li>

View File

@@ -38,7 +38,7 @@
isApplied: true, isApplied: true,
}} }}
{@const { code, icon, id, display, title, keyCode, variant } = {@const { code, icon, id, display, title, keyCode, variant } =
KEYMAP_CODES.get(actionId) ?? { code: actionId }} $KEYMAP_CODES.get(actionId) ?? { code: actionId }}
{@const dynamicMapping = keyCode && $osLayout.get(keyCode)} {@const dynamicMapping = keyCode && $osLayout.get(keyCode)}
{@const tooltip = {@const tooltip =
(title ?? id ?? `0x${code.toString(16)}`) + (title ?? id ?? `0x${code.toString(16)}`) +

View File

@@ -0,0 +1,132 @@
import type { RawVersionMeta, VersionMeta } from "./types/meta";
import type { Listing } from "./types/listing";
import type { KeymapCategory } from "./types/actions";
import { browser } from "$app/environment";
let lock: Promise<void> | undefined = undefined;
export async function getMeta(
device: string,
version: string,
fetch: typeof window.fetch = window.fetch,
): Promise<VersionMeta | undefined> {
while (lock) await lock;
let resolveLock!: () => void;
lock = new Promise((resolve) => (resolveLock = resolve));
try {
if (!browser) return fetchMeta(device, version, fetch);
const dbRequest = indexedDB.open("version-meta", 1);
const db = await new Promise<IDBDatabase>((resolve, reject) => {
dbRequest.onsuccess = () => resolve(dbRequest.result);
dbRequest.onerror = () => reject(dbRequest.error);
dbRequest.onupgradeneeded = () => {
const db = dbRequest.result;
db.createObjectStore("meta", { keyPath: ["device", "version"] });
};
});
try {
const readTransaction = db.transaction(["meta"], "readonly");
const store = readTransaction.objectStore("meta");
const itemRequest = store.get([device, version]);
const item = await new Promise<VersionMeta | undefined>((resolve) => {
itemRequest.onsuccess = () => resolve(itemRequest.result);
itemRequest.onerror = () => resolve(undefined);
});
if (item) return item;
const meta = await fetchMeta(device, version);
if (!meta) return undefined;
const putTransaction = db.transaction(["meta"], "readwrite");
const putStore = putTransaction.objectStore("meta");
const putRequest = putStore.put(meta);
await new Promise<void>((resolve, reject) => {
putRequest.onsuccess = () => resolve();
putRequest.onerror = () => reject(putRequest.error);
});
putTransaction.commit();
return meta;
} finally {
db.close();
}
} catch (error) {
console.error(error);
} finally {
resolveLock();
lock = undefined;
}
return undefined;
}
async function fetchMeta(
device: string,
version: string,
fetch: typeof window.fetch = window.fetch,
): Promise<VersionMeta> {
const path = `${import.meta.env.VITE_FIRMWARE_URL}/${device}/${version}`;
const files: Listing[] = await fetch(`${path}/`).then((res) => res.json());
const meta: Partial<RawVersionMeta> | undefined = files.some(
(entry) => entry.type === "file" && entry.name === "meta.json",
)
? await fetch(`${path}/meta.json`).then((res) => res.json())
: undefined;
return {
version: meta?.version ?? version,
device: meta?.target ?? device,
date: new Date(meta?.git_date ?? files[0]?.mtime ?? ""),
path,
commit: meta?.git_commit ?? undefined,
dirty: meta?.git_is_dirty ?? false,
public: meta?.public_build ?? !version.includes("+"),
developmentBuild: (meta?.development_mode ?? 0) === 1,
factoryDefaults: meta?.factory_defaults
? {
layout: await fetch(`${path}/${meta.factory_defaults.layout}`).then(
(it) => it.json(),
),
settings: await fetch(
`${path}/${meta.factory_defaults.settings}`,
).then((it) => it.json()),
chords: Object.fromEntries(
await Promise.all(
Object.entries(meta.factory_defaults.chords).map(
async ([name, file]) => [
name,
await fetch(`${path}/${file}`).then((it) => it.json()),
],
),
),
),
}
: undefined,
actions: await (meta?.actions
? fetch(`${path}/${meta.actions}`).then((it) => it.json())
: Promise.all<KeymapCategory[]>(
Object.values(import.meta.glob("$lib/assets/keymaps/*.yml")).map(
async (load) => load().then((it) => (it as any).default),
),
)),
update: {
uf2:
meta?.update?.uf2 ??
files.find(
(entry) => entry.type === "file" && entry.name === "CURRENT.UF2",
)?.name ??
undefined,
ota:
meta?.update?.ota ??
files.find(
(entry) => entry.type === "file" && entry.name === "firmware.bin",
)?.name ??
undefined,
esptool: meta?.update?.esptool ?? undefined,
},
spiFlash: meta?.spi_flash ?? undefined,
};
}

View File

@@ -0,0 +1,19 @@
export interface KeymapCategory {
name: string;
description: string;
icon?: string;
display?: string;
type?: "unassigned";
actions: Record<number, Partial<ActionInfo>>;
}
export interface ActionInfo {
id: string;
title: string;
icon: string;
display: string;
description: string;
variant: "left" | "right";
variantOf: number;
keyCode: string;
}

View File

@@ -1,4 +1,11 @@
export interface VersionMeta { import type {
CharaChordFile,
CharaLayoutFile,
CharaSettingsFile,
} from "$lib/share/chara-file";
import type { KeymapCategory } from "./actions";
export interface RawVersionMeta {
version: string; version: string;
target: string; target: string;
git_commit: string; git_commit: string;
@@ -6,6 +13,12 @@ export interface VersionMeta {
git_date: string; git_date: string;
public_build: boolean; public_build: boolean;
development_mode: number; development_mode: number;
actions: string;
factory_defaults: {
layout: string;
settings: string;
chords: Record<string, string>;
};
update: { update: {
ota: string | null; ota: string | null;
uf2: string | null; uf2: string | null;
@@ -15,6 +28,29 @@ export interface VersionMeta {
spi_flash: SPIFlashInfo | null; spi_flash: SPIFlashInfo | null;
} }
export interface VersionMeta {
version: string;
device: string;
path: string;
date: Date;
public: boolean;
commit?: string;
dirty: boolean;
developmentBuild: boolean;
actions: KeymapCategory[];
factoryDefaults?: {
layout: CharaLayoutFile;
settings: CharaSettingsFile;
chords: Record<string, CharaChordFile>;
};
update: {
ota?: string;
uf2?: string;
esptool?: EspToolData;
};
spiFlash?: SPIFlashInfo;
}
export interface SPIFlashInfo { export interface SPIFlashInfo {
type: string; type: string;
size: string; size: string;

View File

@@ -6,6 +6,8 @@ import type { CharaLayout } from "$lib/serialization/layout";
import { persistentWritable } from "$lib/storage"; import { persistentWritable } from "$lib/storage";
import { userPreferences } from "$lib/preferences"; import { userPreferences } from "$lib/preferences";
import settingInfo from "$lib/assets/settings.yml"; import settingInfo from "$lib/assets/settings.yml";
import { getMeta } from "$lib/meta/meta-storage";
import type { VersionMeta } from "$lib/meta/types/meta";
export const serialPort = writable<CharaDevice | undefined>(); export const serialPort = writable<CharaDevice | undefined>();
@@ -47,6 +49,8 @@ export const syncStatus: Writable<
"done" | "error" | "downloading" | "uploading" "done" | "error" | "downloading" | "uploading"
> = writable("done"); > = writable("done");
export const deviceMeta = writable<VersionMeta | undefined>(undefined);
export interface ProgressInfo { export interface ProgressInfo {
max: number; max: number;
current: number; current: number;
@@ -65,6 +69,12 @@ export async function initSerial(manual = false, withSync = true) {
export async function sync() { export async function sync() {
const device = get(serialPort); const device = get(serialPort);
if (!device) return; if (!device) return;
getMeta(
`${device.device}_${device.chipset}`.toLowerCase(),
device.version.toString(),
).then((meta) => {
deviceMeta.set(meta);
});
const chordCount = await device.getChordCount(); const chordCount = await device.getChordCount();
syncStatus.set("downloading"); syncStatus.set("downloading");

View File

@@ -1,38 +1,64 @@
import type { ActionInfo, KeymapCategory } from "$lib/assets/keymaps/keymap"; import type { ActionInfo, KeymapCategory } from "$lib/assets/keymaps/keymap";
import { derived, type Readable } from "svelte/store";
import { deviceMeta } from "./connection";
export interface KeyInfo extends Partial<ActionInfo> { export interface KeyInfo extends Partial<ActionInfo> {
code: number; code: number;
category?: KeymapCategory; category?: KeymapCategory;
} }
export const KEYMAP_CATEGORIES = (await Promise.all( const fallbackActions = await Promise.all<KeymapCategory>(
Object.values(import.meta.glob("$lib/assets/keymaps/*.yml")).map( Object.values(import.meta.glob("$lib/assets/keymaps/*.yml")).map(
async (load) => load().then((it) => (it as any).default), async (load) => load().then((it) => (it as any).default),
), ),
)) as KeymapCategory[];
export const KEYMAP_CODES = new Map<number, KeyInfo>(
KEYMAP_CATEGORIES.flatMap((category) =>
Object.entries(category.actions).map(([code, action]) => [
Number(code),
{ ...action, code: Number(code), category },
]),
),
); );
export const KEYMAP_KEYCODES = new Map<string, number>( export let KEYMAP_CATEGORIES: Readable<KeymapCategory[]> = derived(
KEYMAP_CATEGORIES.flatMap((category) => deviceMeta,
Object.entries(category.actions).map( (deviceMeta) => deviceMeta?.actions ?? fallbackActions,
([code, action]) => [action.keyCode!, Number(code)] as const, );
export const KEYMAP_CODES: Readable<Map<number, KeyInfo>> = derived(
KEYMAP_CATEGORIES,
(categories) =>
new Map<number, KeyInfo>(
categories.flatMap((category) =>
Object.entries(category.actions).map(([code, action]) => [
Number(code),
{ ...action, code: Number(code), category },
]),
),
), ),
).filter(([keyCode]) => keyCode !== undefined),
); );
export const KEYMAP_IDS = new Map<string, KeyInfo>( export const KEYMAP_KEYCODES: Readable<Map<string, number>> = derived(
KEYMAP_CATEGORIES.flatMap((category) => KEYMAP_CATEGORIES,
Object.entries(category.actions).map( (categories) =>
([code, action]) => new Map<string, number>(
[action.id!, { ...action, code: Number(code), category }] as const, categories
.flatMap((category) =>
Object.entries(category.actions).map(
([code, action]) => [action.keyCode!, Number(code)] as const,
),
)
.filter(([keyCode]) => keyCode !== undefined),
),
);
export const KEYMAP_IDS: Readable<Map<string, KeyInfo>> = derived(
KEYMAP_CATEGORIES,
(categories) =>
new Map<string, KeyInfo>(
categories
.flatMap((category) =>
Object.entries(category.actions).map(
([code, action]) =>
[
action.id!,
{ ...action, code: Number(code), category },
] as const,
),
)
.filter(([id]) => id !== undefined),
), ),
).filter(([id]) => id !== undefined),
); );

View File

@@ -107,57 +107,61 @@ export type ChordInfo = Chord &
id: number[]; id: number[];
deleted: boolean; deleted: boolean;
}; };
export const chords = derived([overlay, deviceChords], ([overlay, chords]) => { export const chords = derived(
const newChords = new Set(overlay.chords.keys()); [overlay, deviceChords, KEYMAP_CODES],
([overlay, chords, codes]) => {
const newChords = new Set(overlay.chords.keys());
const changedChords = chords.map<ChordInfo>((chord) => { const changedChords = chords.map<ChordInfo>((chord) => {
const id = JSON.stringify(chord.actions); const id = JSON.stringify(chord.actions);
if (overlay.chords.has(id)) { if (overlay.chords.has(id)) {
newChords.delete(id); newChords.delete(id);
const changedChord = overlay.chords.get(id)!; const changedChord = overlay.chords.get(id)!;
return { return {
id: chord.actions, id: chord.actions,
// use the old phrase for stable editing // use the old phrase for stable editing
sortBy: chord.phrase.map((it) => KEYMAP_CODES.get(it)?.id ?? it).join(), sortBy: chord.phrase.map((it) => codes.get(it)?.id ?? it).join(),
actions: changedChord.actions, actions: changedChord.actions,
phrase: changedChord.phrase, phrase: changedChord.phrase,
actionsChanged: id !== JSON.stringify(changedChord.actions), actionsChanged: id !== JSON.stringify(changedChord.actions),
phraseChanged: phraseChanged:
JSON.stringify(chord.phrase) !== JSON.stringify(changedChord.phrase), JSON.stringify(chord.phrase) !==
isApplied: false, JSON.stringify(changedChord.phrase),
deleted: changedChord.deleted, isApplied: false,
}; deleted: changedChord.deleted,
} else { };
return { } else {
id: chord.actions, return {
sortBy: chord.phrase.map((it) => KEYMAP_CODES.get(it)?.id ?? it).join(), id: chord.actions,
actions: chord.actions, sortBy: chord.phrase.map((it) => codes.get(it)?.id ?? it).join(),
phrase: chord.phrase, actions: chord.actions,
phraseChanged: false, phrase: chord.phrase,
actionsChanged: false, phraseChanged: false,
isApplied: true, actionsChanged: false,
deleted: false, isApplied: true,
}; deleted: false,
} };
}); }
for (const id of newChords) {
const chord = overlay.chords.get(id)!;
changedChords.push({
sortBy: "",
isApplied: false,
actionsChanged: true,
phraseChanged: false,
deleted: chord.deleted,
id: JSON.parse(id),
phrase: chord.phrase,
actions: chord.actions,
}); });
} for (const id of newChords) {
const chord = overlay.chords.get(id)!;
changedChords.push({
sortBy: "",
isApplied: false,
actionsChanged: true,
phraseChanged: false,
deleted: chord.deleted,
id: JSON.parse(id),
phrase: chord.phrase,
actions: chord.actions,
});
}
return changedChords.sort(({ sortBy: a }, { sortBy: b }) => return changedChords.sort(({ sortBy: a }, { sortBy: b }) =>
a.localeCompare(b), a.localeCompare(b),
); );
}); },
);
export const chordHashes = derived( export const chordHashes = derived(
chords, chords,

View File

@@ -1,6 +0,0 @@
{
"CHARACHORDER ONE M0": {
"latest": "1.1.3",
"next": null
}
}

View File

@@ -1,8 +1,8 @@
import type { PageLoad } from "./$types"; import type { PageLoad } from "./$types";
import type { DirectoryListing } from "./listing"; import type { DirectoryListing } from "$lib/meta/types/listing";
export const load = (async ({ fetch }) => { export const load = (async ({ fetch }) => {
const result = await fetch(import.meta.env.VITE_FIRMWARE_URL); const result = await fetch(`${import.meta.env.VITE_FIRMWARE_URL}/`);
const data = await result.json(); const data = await result.json();
return { devices: data as DirectoryListing[] }; return { devices: data as DirectoryListing[] };

View File

@@ -1,5 +1,5 @@
import type { PageLoad } from "./$types"; import type { PageLoad } from "./$types";
import type { DirectoryListing } from "../listing"; import type { DirectoryListing } from "$lib/meta/types/listing";
export const load = (async ({ fetch, params }) => { export const load = (async ({ fetch, params }) => {
const result = await fetch( const result = await fetch(

View File

@@ -27,7 +27,7 @@
$serialPort = undefined; $serialPort = undefined;
try { try {
const file = await fetch( const file = await fetch(
`${data.meta.path}/${data.meta.update.ota?.name}`, `${data.meta.path}/${data.meta.update.ota}`,
).then((it) => it.blob()); ).then((it) => it.blob());
await port.updateFirmware(file); await port.updateFirmware(file);
@@ -46,7 +46,7 @@
: undefined, : undefined,
); );
let isCorrectDevice = $derived( let isCorrectDevice = $derived(
currentDevice ? currentDevice === data.meta.target : undefined, currentDevice ? currentDevice === data.meta.device : undefined,
); );
/** /**
@@ -84,11 +84,11 @@
async function getFileSystem() { async function getFileSystem() {
if (!data.meta.update.uf2) return; if (!data.meta.update.uf2) return;
const uf2Promise = fetch( const uf2Promise = fetch(`${data.meta.path}/${data.meta.update.uf2}`).then(
`${data.meta.path}/${data.meta.update.uf2.name}`, (it) => it.blob(),
).then((it) => it.blob()); );
const handle = await window.showSaveFilePicker({ const handle = await window.showSaveFilePicker({
id: `${data.meta.target}-update`, id: `${data.meta.device}-update`,
suggestedName: "CURRENT.UF2", suggestedName: "CURRENT.UF2",
excludeAcceptAllOption: true, excludeAcceptAllOption: true,
types: [ types: [
@@ -172,7 +172,7 @@
const port = await navigator.serial.requestPort(); const port = await navigator.serial.requestPort();
try { try {
console.log(data.meta); console.log(data.meta);
const spiFlash = data.meta.spi_flash!; const spiFlash = data.meta.spiFlash!;
espLoader = await connectEsp(port); espLoader = await connectEsp(port);
/*espLoader.flashSpiAttach( /*espLoader.flashSpiAttach(
@@ -189,7 +189,7 @@
</script> </script>
<div class="container"> <div class="container">
{#if data.meta.update.ota && !data.meta.target.endsWith("m0")} {#if data.meta.update.ota && !data.meta.device.endsWith("m0")}
{@const buttonError = error || (!success && isCorrectDevice === false)} {@const buttonError = error || (!success && isCorrectDevice === false)}
<section> <section>
<button <button

View File

@@ -1,50 +1,14 @@
import type { PageLoad } from "./$types"; import type { PageLoad } from "./$types";
import type { FileListing, Listing } from "../../listing"; import { getMeta } from "$lib/meta/meta-storage";
import type { VersionMeta } from "$lib/meta"; import { error } from "@sveltejs/kit";
export const load = (async ({ fetch, params }) => { export const load = (async ({ fetch, params }) => {
const result = await fetch( const meta = await getMeta(params.device, params.version, fetch);
`${import.meta.env.VITE_FIRMWARE_URL}/${params.device}/${params.version}/`, if (meta === undefined) {
); error(
const data: Listing[] = await result.json(); 404,
const meta: VersionMeta | undefined = data.some( `The version ${params.version} for device ${params.device} does not exist.`,
(entry) => entry.type === "file" && entry.name === "meta.json", );
) }
? await fetch( return { meta };
`${import.meta.env.VITE_FIRMWARE_URL}/${params.device}/${params.version}/meta.json`,
).then((res) => res.json())
: undefined;
return {
meta: {
version: meta?.version ?? params.version,
target: meta?.target ?? params.device,
path: `${import.meta.env.VITE_FIRMWARE_URL}${params.device}/${params.version}`,
git_commit: meta?.git_commit ?? "",
git_is_dirty: meta?.git_is_dirty ?? false,
git_date: meta?.git_date ?? data[0]?.mtime ?? "",
public_build: meta?.public_build ?? !params.version.includes("+"),
development_mode: meta?.development_mode ?? 0,
update: {
uf2:
(data.find(
(entry) =>
entry.type === "file" &&
entry.name === (meta?.update?.uf2 ?? "CURRENT.UF2"),
) as FileListing) ?? undefined,
ota:
data.find(
(entry) =>
entry.type === "file" &&
entry.name === (meta?.update?.ota ?? "firmware.bin"),
) ?? undefined,
esptool: meta?.update?.esptool ?? undefined,
},
files: data.filter(
(entry) =>
entry.type === "file" && (!meta?.files || entry.name in meta.files),
) as FileListing[],
spi_flash: meta?.spi_flash ?? undefined,
},
};
}) satisfies PageLoad; }) satisfies PageLoad;

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { initMatrixClient, isLoggedIn, matrix } from "$lib/chat/chat"; import { initMatrixClient, isLoggedIn, matrix } from "$lib/chat/chat-rx";
import { flip } from "svelte/animate"; import { flip } from "svelte/animate";
import { slide } from "svelte/transition"; import { slide } from "svelte/transition";
import Login from "./Login.svelte"; import Login from "./Login.svelte";

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { KEYMAP_CODES } from "$lib/serial/keymap-codes"; import { KEYMAP_CODES, type KeyInfo } from "$lib/serial/keymap-codes";
import FlexSearch from "flexsearch"; import FlexSearch from "flexsearch";
import LL from "$i18n/i18n-svelte"; import LL from "$i18n/i18n-svelte";
import { action } from "$lib/title"; import { action } from "$lib/title";
@@ -40,16 +40,21 @@
$effect(() => { $effect(() => {
abortIndexing?.(); abortIndexing?.();
progress = 0; progress = 0;
buildIndex($chords, $osLayout).then(searchIndex.set); buildIndex($chords, $osLayout, $KEYMAP_CODES).then(searchIndex.set);
}); });
function encodeChord(chord: ChordInfo, osLayout: Map<string, string>, onlyPhrase: boolean = false) { function encodeChord(
chord: ChordInfo,
osLayout: Map<string, string>,
codes: Map<number, KeyInfo>,
onlyPhrase: boolean = false,
) {
const plainPhrase: string[] = [""]; const plainPhrase: string[] = [""];
const extraActions: string[] = []; const extraActions: string[] = [];
const extraCodes: string[] = []; const extraCodes: string[] = [];
for (const actionCode of chord.phrase ?? []) { for (const actionCode of chord.phrase ?? []) {
const action = KEYMAP_CODES.get(actionCode); const action = codes.get(actionCode);
if (!action) { if (!action) {
extraCodes.push(`0x${actionCode.toString(16)}`); extraCodes.push(`0x${actionCode.toString(16)}`);
continue; continue;
@@ -96,7 +101,7 @@
const input = chord.actions const input = chord.actions
.slice(chord.actions.lastIndexOf(0) + 1) .slice(chord.actions.lastIndexOf(0) + 1)
.map((it) => { .map((it) => {
const info = KEYMAP_CODES.get(it); const info = codes.get(it);
if (!info) return `0x${it.toString(16)}`; if (!info) return `0x${it.toString(16)}`;
const osCode = info.keyCode && osLayout.get(info.keyCode); const osCode = info.keyCode && osLayout.get(info.keyCode);
const result = osCode?.length === 1 ? osCode : info.id; const result = osCode?.length === 1 ? osCode : info.id;
@@ -118,6 +123,7 @@
async function buildIndex( async function buildIndex(
chords: ChordInfo[], chords: ChordInfo[],
osLayout: Map<string, string>, osLayout: Map<string, string>,
codes: Map<number, KeyInfo>,
): Promise<FlexSearch.Index> { ): Promise<FlexSearch.Index> {
if (chords.length === 0 || !browser) return index; if (chords.length === 0 || !browser) return index;
index = new FlexSearch.Index({ index = new FlexSearch.Index({
@@ -148,7 +154,7 @@
progress = i; progress = i;
if ("phrase" in chord) { if ("phrase" in chord) {
await index.addAsync(i, encodeChord(chord, osLayout)); await index.addAsync(i, encodeChord(chord, osLayout, codes));
} }
} }
return index; return index;
@@ -186,7 +192,9 @@
function downloadVocabulary() { function downloadVocabulary() {
const vocabulary = new Set( const vocabulary = new Set(
$chords.map((it) => $chords.map((it) =>
"phrase" in it ? encodeChord(it, $osLayout, true).trim() : "", "phrase" in it
? encodeChord(it, $osLayout, $KEYMAP_CODES, true).trim()
: "",
), ),
); );
vocabulary.delete(""); vocabulary.delete("");

View File

@@ -23,7 +23,7 @@ process.env["VITE_LEARN_URL"] = "https://www.iq-eq.io/";
process.env["VITE_LATEST_FIRMWARE"] = "1.1.4"; process.env["VITE_LATEST_FIRMWARE"] = "1.1.4";
process.env["VITE_STORE_URL"] = "https://www.charachorder.com/"; process.env["VITE_STORE_URL"] = "https://www.charachorder.com/";
process.env["VITE_MATRIX_URL"] = "https://charachorder.io/"; process.env["VITE_MATRIX_URL"] = "https://charachorder.io/";
process.env["VITE_FIRMWARE_URL"] = "https://charachorder.io/firmware/"; process.env["VITE_FIRMWARE_URL"] = "https://charachorder.io/firmware";
export default defineConfig({ export default defineConfig({
build: { build: {