@fish-under-sea/magpie-neartoken 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.mjs +61 -1
- package/package.json +1 -1
- package/page/app.js +124 -9
- package/page/groups.js +2 -0
- package/page/icon.png +0 -0
- package/page/icon.svg +27 -4
- package/page/index.html +7 -4
- package/page/latest.js +2 -0
- package/page/style.css +16 -1
- package/page/version.js +1 -1
package/index.mjs
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// 站点自己的 /v1/models 按令牌分组过滤,很多账号拿到的是空列表,所以模型目录
|
|
13
13
|
// 直接读 /api/pricing(公开、全量),不靠那个端点。
|
|
14
14
|
|
|
15
|
-
import { readFileSync } from 'node:fs'
|
|
15
|
+
import { readFileSync, writeFileSync } from 'node:fs'
|
|
16
16
|
import { dirname, join } from 'node:path'
|
|
17
17
|
import { fileURLToPath } from 'node:url'
|
|
18
18
|
|
|
@@ -118,6 +118,9 @@ const hasWord = (id, words) => words.some((w) => id.toLowerCase().includes(w))
|
|
|
118
118
|
* 按那一行走那一组——这就是"模型后面跟着它的分组"。
|
|
119
119
|
*/
|
|
120
120
|
async function catalog(disabled = new Set()) {
|
|
121
|
+
// 同时把「全部分组」抄一份给页面:页面在沙箱里发不出网络请求,但能加载自己
|
|
122
|
+
// 目录下的脚本,所以这里写 page/groups.js,模型广场按它重绘。
|
|
123
|
+
const groupsOut = new Map()
|
|
121
124
|
const env = await call('/api/pricing')
|
|
122
125
|
const rows = Array.isArray(env?.data) ? env.data : []
|
|
123
126
|
const refs = env?.group_refs && typeof env.group_refs === 'object' ? env.group_refs : {}
|
|
@@ -132,6 +135,13 @@ async function catalog(disabled = new Set()) {
|
|
|
132
135
|
const film = hasWord(model, FILMS)
|
|
133
136
|
if (!chat && !drawer && !film) continue
|
|
134
137
|
const all = Array.isArray(row?.enable_groups) && row.enable_groups.length ? row.enable_groups : ['']
|
|
138
|
+
// 先按「全部分组」计数(关掉的也算),模型广场要显示它有多少个模型
|
|
139
|
+
for (const raw of all) {
|
|
140
|
+
const g = String(raw ?? '').trim()
|
|
141
|
+
if (!g) continue
|
|
142
|
+
const had = groupsOut.get(g)
|
|
143
|
+
groupsOut.set(g, { name: g, ratio: 0, models: (had?.models || 0) + 1, ref: '' })
|
|
144
|
+
}
|
|
135
145
|
const groups = all.filter((g) => !disabled.has(String(g ?? '').trim()))
|
|
136
146
|
if (!groups.length) continue
|
|
137
147
|
for (const raw of groups) {
|
|
@@ -156,9 +166,57 @@ async function catalog(disabled = new Set()) {
|
|
|
156
166
|
}
|
|
157
167
|
}
|
|
158
168
|
}
|
|
169
|
+
writeGroups([...groupsOut.values()].map((g) => ({
|
|
170
|
+
...g,
|
|
171
|
+
ratio: Number(ratios[g.name]) > 0 ? Number(ratios[g.name]) : 0,
|
|
172
|
+
ref: refs[g.name] ? String(refs[g.name]) : '',
|
|
173
|
+
})).sort((a, b) => a.name.localeCompare(b.name, 'zh')))
|
|
159
174
|
return out
|
|
160
175
|
}
|
|
161
176
|
|
|
177
|
+
/**
|
|
178
|
+
* writeGroups 把分组表写成 page/groups.js,给沙箱里的页面用。
|
|
179
|
+
*
|
|
180
|
+
* 页面发不出网络请求(CSP connect-src 'none'),但能加载自己目录下的脚本,
|
|
181
|
+
* 所以这里不推数据、只落一个文件:`<script src="groups.js?t=…">` 一引就有。
|
|
182
|
+
* 写不进去(插件目录只读)就跳过,页面退回它自己的说明。
|
|
183
|
+
*/
|
|
184
|
+
/**
|
|
185
|
+
* stampLatest 把 npm 上的最新版本写进 page/latest.js。
|
|
186
|
+
*
|
|
187
|
+
* 页面自己查不了(沙箱禁联网),但插件能:这里顺手问一次 registry,页面
|
|
188
|
+
* 「检查更新」时加载这个脚本就知道新不新。一分钟内不重复问。
|
|
189
|
+
*/
|
|
190
|
+
let latestAskedAt = 0
|
|
191
|
+
async function stampLatest() {
|
|
192
|
+
if (Date.now() - latestAskedAt < 60_000) return
|
|
193
|
+
latestAskedAt = Date.now()
|
|
194
|
+
try {
|
|
195
|
+
const res = await fetch('https://registry.npmjs.org/@fish-under-sea%2Fmagpie-neartoken/latest', {
|
|
196
|
+
headers: { accept: 'application/json' },
|
|
197
|
+
})
|
|
198
|
+
if (!res.ok) return
|
|
199
|
+
const body = await res.json()
|
|
200
|
+
const v = typeof body?.version === 'string' ? body.version.trim() : ''
|
|
201
|
+
if (!v) return
|
|
202
|
+
writeFileSync(
|
|
203
|
+
join(here, 'page', 'latest.js'),
|
|
204
|
+
'self.NEARTOKEN_LATEST = ' + JSON.stringify(v) + '\nself.NEARTOKEN_LATEST_AT = ' + Date.now() + '\n',
|
|
205
|
+
'utf8',
|
|
206
|
+
)
|
|
207
|
+
} catch {
|
|
208
|
+
/* 问不到就保持原样:页面会说「没查到」 */
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function writeGroups(groups) {
|
|
212
|
+
try {
|
|
213
|
+
const js = 'self.NEARTOKEN_GROUPS = ' + JSON.stringify(groups) + '\nself.NEARTOKEN_GROUPS_AT = ' + Date.now() + '\n'
|
|
214
|
+
writeFileSync(join(here, 'page', 'groups.js'), js, 'utf8')
|
|
215
|
+
} catch {
|
|
216
|
+
/* 只读安装:页面自己会说没拿到明细 */
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
162
220
|
export default async function neartoken(input, options) {
|
|
163
221
|
// 页面写进来的开关:关掉的分组,它们的模型不再出现在 magpie 的列表里。
|
|
164
222
|
// 走的是 magpie 的 plugin options(页面 magpie.options.set),不碰宿主代码。
|
|
@@ -241,6 +299,7 @@ export default async function neartoken(input, options) {
|
|
|
241
299
|
],
|
|
242
300
|
/** 余额:站点钱包端点,按 magpie 的用量卡显示。 */
|
|
243
301
|
async usage(getAuth) {
|
|
302
|
+
await stampLatest()
|
|
244
303
|
const auth = await getAuth()
|
|
245
304
|
const key = auth?.access || auth?.key
|
|
246
305
|
if (!key) throw new Error('还没有连接 NearToken')
|
|
@@ -291,6 +350,7 @@ export default async function neartoken(input, options) {
|
|
|
291
350
|
* @returns {Promise<Record<string, object>>}
|
|
292
351
|
*/
|
|
293
352
|
async models() {
|
|
353
|
+
await stampLatest()
|
|
294
354
|
return catalog(disabled)
|
|
295
355
|
},
|
|
296
356
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fish-under-sea/magpie-neartoken",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "NearToken for magpie: a provider whose sign-in is the site's own device authorization, models listed per billing group with their multiplier, balance and vouchers on magpie's usage card, plus a page for spending and top-ups.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.mjs",
|
package/page/app.js
CHANGED
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
let disabledGroups = new Set()
|
|
24
24
|
/** 当前视角:home / market / logs。 */
|
|
25
25
|
let tab = 'home'
|
|
26
|
+
/** 插件写下的分组快照(page/groups.js),页面加载脚本取到。 */
|
|
27
|
+
let groupSnapshot = null
|
|
28
|
+
let groupsAsked = false
|
|
26
29
|
const pick = { amount: null, method: null, custom: '' }
|
|
27
30
|
/** 正在等宿主的哪个动作。 */
|
|
28
31
|
let pendingAct = ''
|
|
@@ -152,8 +155,9 @@
|
|
|
152
155
|
function tick() {
|
|
153
156
|
tickCount += 1
|
|
154
157
|
const counting = view && view.pending
|
|
155
|
-
|
|
156
|
-
|
|
158
|
+
// 等确认时每秒问一次:站点那边一点批准,这边下一拍就能接上
|
|
159
|
+
if (counting) load().catch(() => {})
|
|
160
|
+
else if (tickCount % 60 === 0) load().catch(() => {})
|
|
157
161
|
if (counting) paintCountdown()
|
|
158
162
|
}
|
|
159
163
|
|
|
@@ -215,6 +219,9 @@
|
|
|
215
219
|
if (key !== 'home' && view.configured && !windows.has(span)) {
|
|
216
220
|
call('neartoken:usage', { range: span }).then((w) => { windows.set(span, w); render() }).catch(showError)
|
|
217
221
|
}
|
|
222
|
+
if (key === 'market' && !groupSnapshot) {
|
|
223
|
+
loadGroups().then((got) => { if (got) render() })
|
|
224
|
+
}
|
|
218
225
|
},
|
|
219
226
|
}, label)))
|
|
220
227
|
}
|
|
@@ -247,6 +254,11 @@
|
|
|
247
254
|
onclick: () => act('打开确认页', () => call('neartoken:open')),
|
|
248
255
|
}, '打开确认页'),
|
|
249
256
|
el('button', { disabled: !!pendingAct, onclick: () => copy(p.verificationUriComplete) }, '复制链接'),
|
|
257
|
+
el('button', {
|
|
258
|
+
class: 'ghost',
|
|
259
|
+
disabled: !!pendingAct,
|
|
260
|
+
onclick: () => { load().catch(() => {}) },
|
|
261
|
+
}, '我已确认,立即刷新'),
|
|
250
262
|
el('button', {
|
|
251
263
|
class: 'ghost',
|
|
252
264
|
disabled: !!pendingAct,
|
|
@@ -376,6 +388,39 @@
|
|
|
376
388
|
return card('充值', ...parts)
|
|
377
389
|
}
|
|
378
390
|
|
|
391
|
+
/**
|
|
392
|
+
* loadGroups 取分组快照。
|
|
393
|
+
*
|
|
394
|
+
* 页面在沙箱里发不出网络请求(CSP connect-src 'none'),但能加载自己目录下的
|
|
395
|
+
* 脚本;插件(index.mjs)每次拉目录都会写一份 page/groups.js,这里引一下就有。
|
|
396
|
+
*/
|
|
397
|
+
function loadGroups(force) {
|
|
398
|
+
if (groupsAsked && !force) return Promise.resolve(groupSnapshot)
|
|
399
|
+
groupsAsked = true
|
|
400
|
+
return new Promise((resolve) => {
|
|
401
|
+
const s = document.createElement('script')
|
|
402
|
+
s.src = 'groups.js?t=' + Date.now()
|
|
403
|
+
s.onload = () => {
|
|
404
|
+
groupSnapshot = Array.isArray(self.NEARTOKEN_GROUPS) ? self.NEARTOKEN_GROUPS : null
|
|
405
|
+
resolve(groupSnapshot)
|
|
406
|
+
}
|
|
407
|
+
s.onerror = () => resolve(null)
|
|
408
|
+
document.head.append(s)
|
|
409
|
+
})
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/** retryGroups 让插件重新拉一次目录(刷新模型表也顺手刷新了这份快照)。 */
|
|
413
|
+
async function retryGroups() {
|
|
414
|
+
groupSnapshot = null
|
|
415
|
+
render()
|
|
416
|
+
try {
|
|
417
|
+
await bridge.call('neartoken:refresh', {})
|
|
418
|
+
} catch {
|
|
419
|
+
/* 刷新失败也让下面的读取照跑一次 */
|
|
420
|
+
}
|
|
421
|
+
await loadGroups(true)
|
|
422
|
+
render()
|
|
423
|
+
}
|
|
379
424
|
/** 分组落在哪一类:低价 / 满血 / 图片 / 视频 / 语音 / 向量 / 其他。 */
|
|
380
425
|
function bucketOf(name) {
|
|
381
426
|
const n = String(name || '')
|
|
@@ -391,19 +436,18 @@
|
|
|
391
436
|
|
|
392
437
|
/** 模型广场:按站点返回的分组重绘,分组即为开关。 */
|
|
393
438
|
function marketCard() {
|
|
394
|
-
const list = Array.isArray(view.groupList) ? view.groupList :
|
|
439
|
+
const list = Array.isArray(view.groupList) && view.groupList.length ? view.groupList : groupSnapshot
|
|
395
440
|
const head = el('div', { class: 'row' },
|
|
396
441
|
el('h2', { class: 'grow', text: '分组', style: 'margin:0' }),
|
|
397
442
|
el('a', { class: 'link', href: 'https://neartoken.cc/pricing', target: '_blank', rel: 'noreferrer' }, '站点广场 ↗'))
|
|
398
443
|
if (!list || !list.length) {
|
|
399
444
|
return card(null, head,
|
|
400
445
|
el('p', { class: 'note' },
|
|
401
|
-
'
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
'
|
|
405
|
-
el('a', { class: 'link', href: 'https://neartoken.cc/pricing', target: '_blank', rel: 'noreferrer' }, '站点广场')
|
|
406
|
-
' 看分组与倍率。'))
|
|
446
|
+
'还没拿到分组表。点「重新读取」——插件会去站点拉一次 /api/pricing,',
|
|
447
|
+
'写成 page/groups.js,页面加载它就有数据(不需要宿主改动)。'),
|
|
448
|
+
el('div', { class: 'row', style: 'margin-top:10px' },
|
|
449
|
+
el('button', { class: 'ghost', onclick: () => retryGroups() }, '重新读取'),
|
|
450
|
+
el('a', { class: 'link', href: 'https://neartoken.cc/pricing', target: '_blank', rel: 'noreferrer', style: 'align-self:center' }, '站点广场 ↗')) )
|
|
407
451
|
}
|
|
408
452
|
const buckets = new Map()
|
|
409
453
|
for (const g of list) {
|
|
@@ -604,6 +648,77 @@
|
|
|
604
648
|
act('断开连接', () => call('neartoken:disconnect'))
|
|
605
649
|
})
|
|
606
650
|
|
|
651
|
+
// ---------- 检查更新 ----------
|
|
652
|
+
|
|
653
|
+
/** cmp 比两段版本号:a 比 b 新返回正数。只认数字段,够用了。 */
|
|
654
|
+
function cmpVersion(a, b) {
|
|
655
|
+
const pa = String(a).split(/[.-]/).map((x) => parseInt(x, 10) || 0)
|
|
656
|
+
const pb = String(b).split(/[.-]/).map((x) => parseInt(x, 10) || 0)
|
|
657
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i += 1) {
|
|
658
|
+
const d = (pa[i] || 0) - (pb[i] || 0)
|
|
659
|
+
if (d) return d
|
|
660
|
+
}
|
|
661
|
+
return 0
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* loadLatest 取 npm 上的最新版本。
|
|
666
|
+
*
|
|
667
|
+
* 页面自己查不了,插件会把结果写成 page/latest.js;这里用 script 引入,
|
|
668
|
+
* 加 ?t= 破缓存,所以点一次「检查更新」就是现问一次。
|
|
669
|
+
*/
|
|
670
|
+
function loadLatest() {
|
|
671
|
+
return new Promise((resolve) => {
|
|
672
|
+
const s = document.createElement('script')
|
|
673
|
+
s.src = 'latest.js?t=' + Date.now()
|
|
674
|
+
s.onload = () => resolve(typeof self.NEARTOKEN_LATEST === 'string' ? self.NEARTOKEN_LATEST : '')
|
|
675
|
+
s.onerror = () => resolve('')
|
|
676
|
+
document.head.append(s)
|
|
677
|
+
})
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
let checking = false
|
|
681
|
+
async function checkUpdate() {
|
|
682
|
+
if (checking) return
|
|
683
|
+
checking = true
|
|
684
|
+
const btn = $('updates')
|
|
685
|
+
const note = $('update-note')
|
|
686
|
+
const was = btn.textContent
|
|
687
|
+
btn.disabled = true
|
|
688
|
+
btn.textContent = '检查中…'
|
|
689
|
+
note.hidden = true
|
|
690
|
+
const latest = await loadLatest()
|
|
691
|
+
const mine = self.NEARTOKEN_VERSION || ''
|
|
692
|
+
checking = false
|
|
693
|
+
btn.disabled = false
|
|
694
|
+
btn.textContent = was
|
|
695
|
+
if (!latest) {
|
|
696
|
+
note.className = 'update-note warn'
|
|
697
|
+
note.textContent = '没查到最新版本:插件还没联网拉过一次,稍后再试。'
|
|
698
|
+
note.hidden = false
|
|
699
|
+
return
|
|
700
|
+
}
|
|
701
|
+
if (mine && cmpVersion(latest, mine) > 0) {
|
|
702
|
+
note.className = 'update-note new'
|
|
703
|
+
note.textContent = '有新版本 v' + latest + '(当前 v' + mine + ')'
|
|
704
|
+
const link = el('a', {
|
|
705
|
+
class: 'link',
|
|
706
|
+
href: 'https://github.com/Fish-under-sea/magpie-neartoken/releases',
|
|
707
|
+
target: '_blank',
|
|
708
|
+
rel: 'noreferrer',
|
|
709
|
+
style: 'margin-left:8px',
|
|
710
|
+
}, '去下载 ↗')
|
|
711
|
+
note.append(link)
|
|
712
|
+
note.hidden = false
|
|
713
|
+
return
|
|
714
|
+
}
|
|
715
|
+
note.className = 'update-note'
|
|
716
|
+
note.textContent = '已是最新 v' + (mine || latest)
|
|
717
|
+
note.hidden = false
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
$('updates').addEventListener('click', checkUpdate)
|
|
721
|
+
|
|
607
722
|
// ---------- 画图 ----------
|
|
608
723
|
|
|
609
724
|
/** stackedChart 画一张按模型堆叠的面积图;模型多于 5 个时余下的合并。 */
|
package/page/groups.js
ADDED
package/page/icon.png
CHANGED
|
Binary file
|
package/page/icon.svg
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" width="256" height="256">
|
|
2
|
+
<defs>
|
|
3
|
+
<radialGradient id="body" cx="38%" cy="30%" r="80%">
|
|
4
|
+
<stop offset="0" stop-color="#FFEFB8"/>
|
|
5
|
+
<stop offset="55%" stop-color="#FFD166"/>
|
|
6
|
+
<stop offset="100%" stop-color="#FFA63A"/>
|
|
7
|
+
</radialGradient>
|
|
8
|
+
<linearGradient id="leaf" x1="0" y1="0" x2="1" y2="1">
|
|
9
|
+
<stop offset="0" stop-color="#A9EBC6"/>
|
|
10
|
+
<stop offset="100%" stop-color="#39A377"/>
|
|
11
|
+
</linearGradient>
|
|
12
|
+
</defs>
|
|
13
|
+
<!-- 叶与梗 -->
|
|
14
|
+
<path d="M128 66c-4-19 6-31 26-35 3 19-7 31-26 35z" fill="url(#leaf)" stroke="#2B7F5C" stroke-width="7" stroke-linejoin="round"/>
|
|
15
|
+
<path d="M125 74c2-9 2-16 1-23" stroke="#2B7F5C" stroke-width="8" stroke-linecap="round" fill="none"/>
|
|
16
|
+
<!-- 果身 -->
|
|
17
|
+
<circle cx="128" cy="152" r="82" fill="url(#body)" stroke="#FFF8E9" stroke-width="10"/>
|
|
18
|
+
<!-- 脸 -->
|
|
19
|
+
<ellipse cx="104" cy="150" rx="7.5" ry="9" fill="#4A3B2A"/>
|
|
20
|
+
<ellipse cx="152" cy="150" rx="7.5" ry="9" fill="#4A3B2A"/>
|
|
21
|
+
<circle cx="101.5" cy="147" r="2.4" fill="#FFFDF4"/>
|
|
22
|
+
<circle cx="149.5" cy="147" r="2.4" fill="#FFFDF4"/>
|
|
23
|
+
<path d="M118 170c6 7 14 7 20 0" stroke="#4A3B2A" stroke-width="7" stroke-linecap="round" fill="none"/>
|
|
24
|
+
<ellipse cx="80" cy="168" rx="13" ry="8" fill="#FF8E7A" opacity="0.55"/>
|
|
25
|
+
<ellipse cx="176" cy="168" rx="13" ry="8" fill="#FF8E7A" opacity="0.55"/>
|
|
26
|
+
<!-- 高光 -->
|
|
27
|
+
<ellipse cx="97" cy="118" rx="24" ry="15" fill="#FFFDF3" opacity="0.5" transform="rotate(-28 97 118)"/>
|
|
5
28
|
</svg>
|
package/page/index.html
CHANGED
|
@@ -14,11 +14,14 @@
|
|
|
14
14
|
<h1>NearToken</h1>
|
|
15
15
|
<p class="sub" id="site">neartoken.cc</p>
|
|
16
16
|
</div>
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
<div class="actions">
|
|
18
|
+
<span class="chip ver" id="version" title="插件版本">v—</span>
|
|
19
|
+
<button class="ghost" id="updates" type="button">检查更新</button>
|
|
20
|
+
<span class="chip" id="status"><span class="dot"></span><span id="status-text">正在读取</span></span>
|
|
21
|
+
<button class="ghost" id="disconnect" type="button" hidden>断开连接</button>
|
|
22
|
+
</div>
|
|
21
23
|
</header>
|
|
24
|
+
<p class="update-note" id="update-note" hidden></p>
|
|
22
25
|
<main id="view" aria-live="polite">
|
|
23
26
|
<div class="card"><p class="brief">正在读取 NearToken 的状态…</p></div>
|
|
24
27
|
</main>
|
package/page/latest.js
ADDED
package/page/style.css
CHANGED
|
@@ -457,4 +457,19 @@ select {
|
|
|
457
457
|
padding: 3px 8px;
|
|
458
458
|
}
|
|
459
459
|
|
|
460
|
-
.ghost.link { text-decoration: none; display: inline-flex; align-items: center; }
|
|
460
|
+
.ghost.link { text-decoration: none; display: inline-flex; align-items: center; }
|
|
461
|
+
/* 头部按钮组:版本、检查更新、状态、断开四件一样高,右对齐 */
|
|
462
|
+
.head { align-items: center; gap: 12px; }
|
|
463
|
+
|
|
464
|
+
.actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
|
|
465
|
+
.actions .chip { height: 28px; display: inline-flex; align-items: center; gap: 6px; padding: 0 10px; }
|
|
466
|
+
.actions .ghost { height: 28px; display: inline-flex; align-items: center; }
|
|
467
|
+
.actions .ghost[disabled] { opacity: 0.6; }
|
|
468
|
+
|
|
469
|
+
.update-note {
|
|
470
|
+
margin: 8px 0 0;
|
|
471
|
+
font-size: 11.5px;
|
|
472
|
+
color: var(--nt-muted);
|
|
473
|
+
}
|
|
474
|
+
.update-note.new { color: var(--nt-accent); }
|
|
475
|
+
.update-note.warn { color: var(--nt-warn, #e0a44a); }
|
package/page/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// 由 scripts/stamp.mjs 生成,别手改:版本号在 package.json。
|
|
2
|
-
self.NEARTOKEN_VERSION = "0.2.
|
|
2
|
+
self.NEARTOKEN_VERSION = "0.2.3"
|