nadesiko3 3.7.21 → 3.7.22

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.
Files changed (155) hide show
  1. package/batch/command.txt +370 -334
  2. package/batch/jsplugin2text.nako3 +1 -1
  3. package/batch/pickup_command.nako3 +12 -0
  4. package/core/command/snako.mts +5 -1
  5. package/core/deno/snako.ts +5 -1
  6. package/core/package-lock.json +382 -21
  7. package/core/package.json +4 -4
  8. package/core/src/nako3.mts +178 -614
  9. package/core/src/nako_basic_plugins.mts +39 -0
  10. package/core/src/nako_core_version.mts +2 -2
  11. package/core/src/nako_csv.mts +0 -1
  12. package/core/src/nako_event.mts +49 -0
  13. package/core/src/nako_gen.mts +291 -202
  14. package/core/src/nako_indent_inline.mts +2 -2
  15. package/core/src/nako_lex_rules.mts +1 -1
  16. package/core/src/nako_parser3.mts +106 -165
  17. package/core/src/nako_parser_async.mts +97 -0
  18. package/core/src/nako_parser_base.mts +4 -55
  19. package/core/src/nako_parser_message.mts +105 -0
  20. package/core/src/nako_parser_operator.mts +93 -0
  21. package/core/src/nako_plugin_manager.mts +260 -0
  22. package/core/src/nako_require.mts +292 -0
  23. package/core/src/nako_runner.mts +191 -0
  24. package/core/src/nako_tokenizer.mts +221 -0
  25. package/core/src/plugin_csv.mts +1 -1
  26. package/core/src/plugin_system.mts +34 -3259
  27. package/core/src/plugin_system_array.mts +699 -0
  28. package/core/src/plugin_system_datetime.mts +368 -0
  29. package/core/src/plugin_system_debug.mts +403 -0
  30. package/core/src/plugin_system_dict.mts +85 -0
  31. package/core/src/plugin_system_json.mts +73 -0
  32. package/core/src/plugin_system_math.mts +383 -0
  33. package/core/src/plugin_system_regexp.mts +120 -0
  34. package/core/src/plugin_system_stdio.mts +86 -0
  35. package/core/src/plugin_system_string.mts +666 -0
  36. package/core/src/plugin_system_timer.mts +152 -0
  37. package/core/src/plugin_system_types.mts +151 -0
  38. package/core/src/plugin_system_url.mts +193 -0
  39. package/core/src/plugin_toml.mts +3 -3
  40. package/core/test/fixtures/README.md +39 -0
  41. package/core/test/fixtures/make_parser_ast_golden.mjs +31 -0
  42. package/core/test/fixtures/parser_ast_golden.json +8027 -0
  43. package/core/test/fixtures/parser_corpus.mjs +120 -0
  44. package/core/test/indent_test.mjs +6 -0
  45. package/core/test/nako_basic_plugins_test.mjs +44 -0
  46. package/core/test/nako_event_test.mjs +85 -0
  47. package/core/test/nako_gen_perf_test.mjs +178 -0
  48. package/core/test/nako_parser_async_test.mjs +112 -0
  49. package/core/test/nako_parser_test.mjs +160 -0
  50. package/core/test/nako_plugin_manager_test.mjs +185 -0
  51. package/core/test/nako_require_test.mjs +153 -0
  52. package/core/test/nako_runner_test.mjs +114 -0
  53. package/core/test/nako_tokenizer_test.mjs +115 -0
  54. package/core/test/plugin_system_debug_test.mjs +141 -0
  55. package/core/test/plugin_system_split_test.mjs +179 -0
  56. package/core/test/plugin_system_test.mjs +6 -0
  57. package/core/tsconfig.json +0 -1
  58. package/package.json +17 -21
  59. package/release/_hash.txt +36 -36
  60. package/release/_script-tags.txt +16 -16
  61. package/release/command.json +1 -1
  62. package/release/command.json.js +1 -1
  63. package/release/command_cnako3.json +1 -1
  64. package/release/command_list.json +1 -1
  65. package/release/edit_main.js +6 -6
  66. package/release/edit_main.js.map +3 -3
  67. package/release/editor.js +6 -6
  68. package/release/plugin_keigo.js.map +3 -3
  69. package/release/plugin_markup.js +46 -46
  70. package/release/plugin_markup.js.map +3 -3
  71. package/release/plugin_weykturtle3d.js +1 -1
  72. package/release/plugin_weykturtle3d.js.map +3 -3
  73. package/release/version.js +2 -2
  74. package/release/version_main.js +2 -2
  75. package/release/version_main.js.map +1 -1
  76. package/release/wnako3.js +186 -213
  77. package/release/wnako3.js.map +4 -4
  78. package/release/wnako3webworker.js +172 -199
  79. package/release/wnako3webworker.js.map +4 -4
  80. package/src/cnako3mod.mjs +7 -2
  81. package/src/cnako3mod.mts +7 -2
  82. package/src/nako_version.mjs +2 -2
  83. package/src/nako_version.mts +2 -2
  84. package/src/plugin_browser_ajax.mjs +4 -4
  85. package/src/plugin_browser_ajax.mts +4 -4
  86. package/src/plugin_browser_audio.mjs +10 -10
  87. package/src/plugin_browser_audio.mts +10 -10
  88. package/src/plugin_browser_camera.mjs +4 -4
  89. package/src/plugin_browser_camera.mts +4 -4
  90. package/src/plugin_browser_canvas.mjs +2 -2
  91. package/src/plugin_browser_canvas.mts +2 -2
  92. package/src/plugin_browser_crypto.mjs +3 -3
  93. package/src/plugin_browser_crypto.mts +3 -3
  94. package/src/plugin_browser_dom_event.mjs +1 -1
  95. package/src/plugin_browser_dom_event.mts +1 -1
  96. package/src/plugin_browser_geolocation.mjs +1 -1
  97. package/src/plugin_browser_geolocation.mts +1 -1
  98. package/src/plugin_browser_hotkey.mjs +1 -1
  99. package/src/plugin_browser_hotkey.mts +1 -1
  100. package/src/plugin_browser_html.mjs +1 -1
  101. package/src/plugin_browser_html.mts +1 -1
  102. package/src/plugin_browser_location.mjs +1 -1
  103. package/src/plugin_browser_location.mts +1 -1
  104. package/src/plugin_browser_speech.mjs +1 -1
  105. package/src/plugin_browser_speech.mts +1 -1
  106. package/src/plugin_browser_storage.mjs +2 -2
  107. package/src/plugin_browser_storage.mts +2 -2
  108. package/src/plugin_httpserver.mjs +3 -3
  109. package/src/plugin_httpserver.mts +3 -3
  110. package/src/plugin_keigo.mjs +2 -2
  111. package/src/plugin_keigo.mts +2 -2
  112. package/src/plugin_node.mjs +48 -48
  113. package/src/plugin_node.mts +53 -53
  114. package/src/plugin_weykturtle3d.mjs +56 -56
  115. package/src/plugin_weykturtle3d.mts +56 -56
  116. package/src/wnako3.mjs +1 -1
  117. package/src/wnako3.mts +1 -1
  118. package/src/wnako3_editor.mjs +5 -5
  119. package/src/wnako3_editor.mts +5 -5
  120. package/src/wnako3mod.mjs +2 -2
  121. package/src/wnako3mod.mts +2 -2
  122. package/core/src/nako3.mjs +0 -1021
  123. package/core/src/nako_ast.mjs +0 -4
  124. package/core/src/nako_colors.mjs +0 -77
  125. package/core/src/nako_core_version.mjs +0 -8
  126. package/core/src/nako_csv.mjs +0 -193
  127. package/core/src/nako_errors.mjs +0 -166
  128. package/core/src/nako_from_dncl.mjs +0 -285
  129. package/core/src/nako_from_dncl2.mjs +0 -347
  130. package/core/src/nako_gen.mjs +0 -2500
  131. package/core/src/nako_global.mjs +0 -138
  132. package/core/src/nako_indent.mjs +0 -442
  133. package/core/src/nako_indent_chars.mjs +0 -29
  134. package/core/src/nako_indent_inline.mjs +0 -361
  135. package/core/src/nako_josi_list.mjs +0 -47
  136. package/core/src/nako_lex_rules.mjs +0 -319
  137. package/core/src/nako_lexer.mjs +0 -794
  138. package/core/src/nako_logger.mjs +0 -221
  139. package/core/src/nako_parser3.mjs +0 -3250
  140. package/core/src/nako_parser_base.mjs +0 -403
  141. package/core/src/nako_parser_const.mjs +0 -37
  142. package/core/src/nako_prepare.mjs +0 -329
  143. package/core/src/nako_reserved_words.mjs +0 -42
  144. package/core/src/nako_source_mapping.mjs +0 -207
  145. package/core/src/nako_test.mjs +0 -37
  146. package/core/src/nako_token.mjs +0 -1
  147. package/core/src/nako_tools.mjs +0 -53
  148. package/core/src/nako_types.mjs +0 -14
  149. package/core/src/plugin_api.mjs +0 -4
  150. package/core/src/plugin_csv.mjs +0 -97
  151. package/core/src/plugin_math.mjs +0 -352
  152. package/core/src/plugin_promise.mjs +0 -102
  153. package/core/src/plugin_system.mjs +0 -3810
  154. package/core/src/plugin_test.mjs +0 -52
  155. package/core/src/plugin_toml.mjs +0 -39
@@ -0,0 +1,115 @@
1
+ /* eslint-disable no-undef */
2
+ import { describe, it } from 'node:test'
3
+ import assert from 'assert'
4
+
5
+ import { NakoCompiler } from '../src/nako3.mjs'
6
+ import { NakoTokenizer } from '../src/nako_tokenizer.mjs'
7
+ import { NakoLogger } from '../src/nako_logger.mjs'
8
+
9
+ /**
10
+ * 字句解析パイプラインを NakoCompiler から分離したモジュールのテスト (#2360)
11
+ */
12
+ describe('nako_tokenizer_test', () => {
13
+ /** 取り込み文を扱わない、単体テスト用のトークナイザを作る */
14
+ const createTokenizer = () => {
15
+ const logger = new NakoLogger()
16
+ return new NakoTokenizer({
17
+ getLogger: () => logger,
18
+ // 取り込み文は扱わないので、何もせず空配列を返す
19
+ replaceRequireStatements: () => [],
20
+ removeRequireStatements: () => []
21
+ })
22
+ }
23
+
24
+ it('rawtokenizeがトークン列を返す', () => {
25
+ const tokenizer = createTokenizer()
26
+ // 単体のトークナイザは関数一覧を持たないため、命令は word になる
27
+ const tokens = tokenizer.rawtokenize('1と2を足す', 0, 'main.nako3')
28
+ const types = tokens.map((t) => t.type)
29
+ assert.ok(types.includes('number'), '数値トークンが含まれること')
30
+ assert.ok(types.includes('word'), '単語トークンが含まれること')
31
+ assert.deepStrictEqual(tokens.filter((t) => t.type === 'number').map((t) => t.value), [1, 2])
32
+ })
33
+
34
+ it('rawtokenizeはpreCodeがcodeの先頭にないとエラーになる', () => {
35
+ const tokenizer = createTokenizer()
36
+ assert.throws(
37
+ () => tokenizer.rawtokenize('「A」を表示', 0, 'main.nako3', '「B」を表示'),
38
+ /preCodeを含める必要があります/
39
+ )
40
+ })
41
+
42
+ it('rawtokenizeがモジュールリストへ自身を追加する', () => {
43
+ const tokenizer = createTokenizer()
44
+ tokenizer.rawtokenize('「A」を表示', 0, 'sample.nako3')
45
+ assert.ok(tokenizer.getModList().includes('sample'))
46
+ })
47
+
48
+ it('全角の記号が半角へ正規化される', () => {
49
+ const tokenizer = createTokenizer()
50
+ // 全角の「=」が半角の「=」として解釈される
51
+ const tokens = tokenizer.rawtokenize('A=1', 0, 'main.nako3')
52
+ const types = tokens.map((t) => t.type)
53
+ assert.ok(types.includes('eq'), '代入のトークンになること')
54
+ })
55
+
56
+ it('トークンに行番号と桁位置が設定される', () => {
57
+ const tokenizer = createTokenizer()
58
+ const tokens = tokenizer.rawtokenize('「A」を表示\n「B」を表示\n', 0, 'main.nako3')
59
+ const second = tokens.filter((t) => t.type === 'string' && t.value === 'B')[0]
60
+ assert.ok(second !== undefined)
61
+ assert.strictEqual(second.line, 1, '2行目のトークンの行番号は1になること')
62
+ })
63
+
64
+ it('コメントのトークンが残る', () => {
65
+ const tokenizer = createTokenizer()
66
+ const tokens = tokenizer.rawtokenize('# これはコメント\n「A」を表示\n', 0, 'main.nako3')
67
+ const comments = tokens.filter((t) => t.type === 'line_comment')
68
+ assert.strictEqual(comments.length, 1)
69
+ })
70
+
71
+ it('lexCodeTokenがstartOffsetを加算する', () => {
72
+ const tokenizer = createTokenizer()
73
+ const res = tokenizer.lexCodeToken('1に2を足す', 0, 'main.nako3', 100)
74
+ const withOffset = res.tokens.filter((t) => t.startOffset !== undefined)
75
+ assert.ok(withOffset.length > 0)
76
+ assert.ok(withOffset.every((t) => t.startOffset >= 100), 'startOffsetが加算されること')
77
+ })
78
+
79
+ it('lexCodeTokenにstartOffsetがnullならオフセットを消す', () => {
80
+ const tokenizer = createTokenizer()
81
+ const res = tokenizer.lexCodeToken('1に2を足す', 0, 'main.nako3', null)
82
+ assert.ok(res.tokens.every((t) => t.startOffset === undefined))
83
+ assert.ok(res.tokens.every((t) => t.endOffset === undefined))
84
+ })
85
+
86
+ it('lexが字句解析の結果を返す', () => {
87
+ const tokenizer = createTokenizer()
88
+ const res = tokenizer.lex('# コメント\n「A」を表示\n', 'main.nako3')
89
+ assert.ok(res.tokens.length > 0)
90
+ assert.strictEqual(res.commentTokens.length, 1)
91
+ assert.deepStrictEqual(res.requireTokens, [])
92
+ })
93
+
94
+ it('NakoCompilerの各メソッドはトークナイザへ委譲される', () => {
95
+ const nako = new NakoCompiler()
96
+ const viaCompiler = nako.rawtokenize('1と2を足す', 0, 'main.nako3')
97
+ const viaTokenizer = nako.tokenizer.rawtokenize('1と2を足す', 0, 'main.nako3')
98
+ assert.deepStrictEqual(viaCompiler.map((t) => t.type), viaTokenizer.map((t) => t.type))
99
+ // getModList もトークナイザが持つモジュールリストを返す
100
+ assert.strictEqual(nako.getModList(), nako.tokenizer.getModList())
101
+ })
102
+
103
+ it('replaceLoggerを呼ぶとトークナイザのロガーも差し替わる', () => {
104
+ const nako = new NakoCompiler()
105
+ const logger = nako.replaceLogger()
106
+ assert.strictEqual(nako.tokenizer.lexer.logger, logger)
107
+ assert.strictEqual(nako.getLogger(), logger)
108
+ })
109
+
110
+ it('文字列展開の中のコードも字句解析される', async () => {
111
+ const nako = new NakoCompiler()
112
+ const g = await nako.runAsync('A=3;「値は{A}です」を表示', 'main.nako3')
113
+ assert.strictEqual(g.log, '値は3です')
114
+ })
115
+ })
@@ -0,0 +1,141 @@
1
+ /* eslint-disable no-undef */
2
+ /**
3
+ * plugin_system_debug.mts のテスト (#2351)
4
+ *
5
+ * plugin_system.mts から分割した「特殊命令」「デバッグ支援」「プラグイン管理」の
6
+ * 命令が、分割後も plugin_system の一部として正しく動作することを確認する。
7
+ */
8
+ import { describe, it } from 'node:test'
9
+ import assert from 'assert'
10
+ import { NakoCompiler } from '../src/nako3.mjs'
11
+ import PluginSystem from '../src/plugin_system.mjs'
12
+ import PluginSystemDebug from '../src/plugin_system_debug.mjs'
13
+
14
+ describe('plugin_system_debug_test', async () => {
15
+ const cmp = async (/** @type {string} */ code, /** @type {string} */ res) => {
16
+ const nako = new NakoCompiler()
17
+ nako.getLogger().debug('code=' + code)
18
+ const g = await nako.runAsync(code, 'main.nako3')
19
+ assert.strictEqual(g.log, res)
20
+ }
21
+
22
+ // --- 分割ファイルの構造 ---
23
+ it('分割ファイルはメタ情報や初期化を持たない', async () => {
24
+ assert.strictEqual(PluginSystemDebug.meta, undefined)
25
+ assert.strictEqual(PluginSystemDebug['初期化'], undefined)
26
+ assert.strictEqual(PluginSystemDebug['!クリア'], undefined)
27
+ })
28
+ it('分割ファイルの命令が plugin_system にマージされている', async () => {
29
+ for (const key of Object.keys(PluginSystemDebug)) {
30
+ assert.strictEqual(PluginSystem[key], PluginSystemDebug[key], `『${key}』がマージされていません`)
31
+ }
32
+ })
33
+ it('分割してもプラグインは plugin_system のまま', async () => {
34
+ assert.strictEqual(PluginSystem.meta.value.pluginName, 'plugin_system')
35
+ await cmp('プラグイン一覧取得して「:」で配列結合して表示', 'plugin_system:plugin_math:plugin_promise:plugin_test:plugin_csv:plugin_toml')
36
+ })
37
+
38
+ // --- 特殊命令 ---
39
+ it('特殊命令 - JS実行', async () => {
40
+ await cmp('「3*7」をJS実行して表示', '21')
41
+ })
42
+ it('特殊命令 - JS関数実行', async () => {
43
+ await cmp('「Math.max」を[3,9,5]でJS関数実行して表示', '9')
44
+ })
45
+ it('特殊命令 - JSメソッド実行', async () => {
46
+ await cmp('「[1,2,3]」の「join」を[「-」]でJSメソッド実行して表示', '1-2-3')
47
+ })
48
+ it('特殊命令 - JSオブジェクト取得', async () => {
49
+ await cmp('A=5;「A」のJSオブジェクト取得して表示', '5')
50
+ })
51
+ it('特殊命令 - 実行', async () => {
52
+ await cmp('F=関数()\n「呼ばれた」を表示\nここまで\nFを実行', '呼ばれた')
53
+ await cmp('●テスト関数とは\n「OK」を表示\nここまで\n「テスト関数」を実行', 'OK')
54
+ // 関数でも文字列(関数名)でもない値はそのまま返る (#938)
55
+ await cmp('123を実行して表示', '123')
56
+ })
57
+ it('特殊命令 - 実行時間計測', async () => {
58
+ await cmp('F=関数()\nそれは1\nここまで\nFの実行時間計測;もし、(それ>=0)ならば「OK」を表示', 'OK')
59
+ })
60
+ it('特殊命令 - AWAIT実行', async () => {
61
+ const nako = new NakoCompiler()
62
+ const code = 'F=「a=>a*2」をJS実行\nFを[21]でAWAIT実行して表示'
63
+ const g = await nako.runAsync(code, 'main.nako3')
64
+ // AWAIT実行はPromiseをawaitするため、実行完了までイベントループを1tick進める
65
+ await new Promise((resolve) => setTimeout(resolve, 10))
66
+ assert.strictEqual(g.log, '42')
67
+ })
68
+ it('特殊命令 - AWAIT実行(配列以外の引数)', async () => {
69
+ const nako = new NakoCompiler()
70
+ const code = 'F=「a=>a*2」をJS実行\nFを21でAWAIT実行して表示'
71
+ const g = await nako.runAsync(code, 'main.nako3')
72
+ await new Promise((resolve) => setTimeout(resolve, 10))
73
+ assert.strictEqual(g.log, '42')
74
+ })
75
+ it('特殊命令 - ナデシコ', async () => {
76
+ await cmp('『「なでしこ」を表示』をナデシコ', 'なでしこ')
77
+ })
78
+
79
+ // --- デバッグ支援 ---
80
+ it('デバッグ支援 - デバッグ表示', async () => {
81
+ const nako = new NakoCompiler()
82
+ const g = await nako.runAsync('「メッセージ」をデバッグ表示', 'main.nako3')
83
+ // 「ファイル名(行番号): メッセージ」の形式で出力される
84
+ assert.ok(g.log.indexOf('メッセージ') >= 0, `想定外の出力: ${g.log}`)
85
+ assert.ok(g.log.indexOf('main.nako3') >= 0, `想定外の出力: ${g.log}`)
86
+ })
87
+ it('デバッグ支援 - ハテナ関数設定と実行', async () => {
88
+ await cmp('「表示」をハテナ関数設定; ?? 2*5', '10')
89
+ await cmp('["JSON_E","表示"]をハテナ関数設定; ?? [1,2]', '[1,2]')
90
+ })
91
+ it('デバッグ支援 - エラー発生', async () => {
92
+ const nako = new NakoCompiler()
93
+ try {
94
+ await nako.runAsync('「わざとエラー」のエラー発生', 'main.nako3')
95
+ } catch (err) {
96
+ assert.ok(String(err.message).indexOf('わざとエラー') >= 0)
97
+ return
98
+ }
99
+ assert.fail('エラーが発生しませんでした')
100
+ })
101
+ it('デバッグ支援 - システム関数一覧取得', async () => {
102
+ await cmp('A=システム関数一覧取得;I=Aから「表示」を配列検索;もし、(I>=0)ならば「OK」を表示', 'OK')
103
+ // 分割ファイル側の命令も一覧に含まれる
104
+ await cmp('A=システム関数一覧取得;I=Aから「デバッグ表示」を配列検索;もし、(I>=0)ならば「OK」を表示', 'OK')
105
+ })
106
+ it('デバッグ支援 - システム関数存在', async () => {
107
+ await cmp('もし、「デバッグ表示」のシステム関数存在ならば「OK」を表示', 'OK')
108
+ await cmp('もし、「存在しない命令XYZ」のシステム関数存在でなければ「OK」を表示', 'OK')
109
+ })
110
+ it('デバッグ支援 - グローバル関数一覧取得', async () => {
111
+ // ユーザー定義関数は「モジュール名__関数名」の形式で登録される
112
+ await cmp(
113
+ '●ホゲとは\n' +
114
+ 'それは1\n' +
115
+ 'ここまで\n' +
116
+ 'A=グローバル関数一覧取得\n' +
117
+ 'I=Aから「main__ホゲ」を配列検索\n' +
118
+ 'もし、(I>=0)ならば「OK」を表示',
119
+ 'OK')
120
+ })
121
+ it('デバッグ支援 - モジュール一覧取得', async () => {
122
+ await cmp('A=モジュール一覧取得;もし、(Aの配列要素数)>=0ならば「OK」を表示', 'OK')
123
+ })
124
+ it('デバッグ支援 - 助詞一覧取得と予約語一覧取得', async () => {
125
+ await cmp('A=助詞一覧取得;もし、(Aの配列要素数)>0ならば「OK」を表示', 'OK')
126
+ await cmp('A=予約語一覧取得;もし、(Aの配列要素数)>0ならば「OK」を表示', 'OK')
127
+ })
128
+
129
+ // --- プラグイン管理 ---
130
+ it('プラグイン管理 - プラグイン名', async () => {
131
+ await cmp('プラグイン名を表示', 'メイン')
132
+ })
133
+ it('プラグイン管理 - プラグイン名設定', async () => {
134
+ await cmp('「テストプラグイン」にプラグイン名設定;プラグイン名を表示', 'テストプラグイン')
135
+ })
136
+ it('プラグイン管理 - 名前空間設定と名前空間ポップ', async () => {
137
+ await cmp('「サブ空間」に名前空間設定;名前空間を表示;名前空間ポップ', 'サブ空間')
138
+ // ポップすると設定前の名前空間に戻る
139
+ await cmp('元=名前空間;「サブ空間」に名前空間設定;名前空間ポップ;もし、(名前空間=元)ならば「OK」を表示', 'OK')
140
+ })
141
+ })
@@ -0,0 +1,179 @@
1
+ /* eslint-disable no-undef */
2
+ /**
3
+ * plugin_system.mts の分割ファイルのテスト (#2351)
4
+ *
5
+ * 肥大化した plugin_system.mts を役割ごとに以下へ分割した。
6
+ * - plugin_system_math.mts : 四則演算・論理演算・ビット演算
7
+ * - plugin_system_string.mts : 文字列処理・置換/トリム・文字変換・指定形式・文字種類
8
+ * - plugin_system_array.mts : 配列操作・二次元配列処理
9
+ * - plugin_system_datetime.mts : 日時処理(簡易)
10
+ * - plugin_system_url.mts : URLエンコード・パラメータ・BASE64・パス操作
11
+ * - plugin_system_types.mts : 型変換
12
+ * - plugin_system_json.mts : JSON
13
+ * - plugin_system_regexp.mts : 正規表現
14
+ * - plugin_system_dict.mts : 辞書型変数の操作・ハッシュ
15
+ * - plugin_system_stdio.mts : 標準出力
16
+ * - plugin_system_timer.mts : タイマー処理
17
+ * いずれも単独のプラグインではなく、plugin_system.mts に実行時マージされる。
18
+ * 個々の命令の詳細な動作テストは plugin_system_test.mjs で従来通りカバーされているため、
19
+ * ここでは「分割ファイルが正しくマージされているか」と代表的な命令の疎通確認を行う。
20
+ */
21
+ import { describe, it } from 'node:test'
22
+ import assert from 'assert'
23
+ import { NakoCompiler } from '../src/nako3.mjs'
24
+ import PluginSystem from '../src/plugin_system.mjs'
25
+ import PluginSystemMath from '../src/plugin_system_math.mjs'
26
+ import PluginSystemString from '../src/plugin_system_string.mjs'
27
+ import PluginSystemArray from '../src/plugin_system_array.mjs'
28
+ import PluginSystemDatetime from '../src/plugin_system_datetime.mjs'
29
+ import PluginSystemUrl from '../src/plugin_system_url.mjs'
30
+ import PluginSystemTypes from '../src/plugin_system_types.mjs'
31
+ import PluginSystemJson from '../src/plugin_system_json.mjs'
32
+ import PluginSystemRegexp from '../src/plugin_system_regexp.mjs'
33
+ import PluginSystemDict from '../src/plugin_system_dict.mjs'
34
+ import PluginSystemStdio from '../src/plugin_system_stdio.mjs'
35
+ import PluginSystemTimer from '../src/plugin_system_timer.mjs'
36
+
37
+ describe('plugin_system_split_test', async () => {
38
+ const cmp = async (/** @type {string} */ code, /** @type {string} */ res) => {
39
+ const nako = new NakoCompiler()
40
+ nako.getLogger().debug('code=' + code)
41
+ const g = await nako.runAsync(code, 'main.nako3')
42
+ assert.strictEqual(g.log, res)
43
+ }
44
+
45
+ const parts = {
46
+ math: PluginSystemMath,
47
+ string: PluginSystemString,
48
+ array: PluginSystemArray,
49
+ datetime: PluginSystemDatetime,
50
+ url: PluginSystemUrl,
51
+ types: PluginSystemTypes,
52
+ json: PluginSystemJson,
53
+ regexp: PluginSystemRegexp,
54
+ dict: PluginSystemDict,
55
+ stdio: PluginSystemStdio,
56
+ timer: PluginSystemTimer
57
+ }
58
+
59
+ it('分割ファイルはメタ情報や初期化を持たない', async () => {
60
+ for (const [name, part] of Object.entries(parts)) {
61
+ assert.strictEqual(part.meta, undefined, `${name}にmetaがあります`)
62
+ assert.strictEqual(part['初期化'], undefined, `${name}に初期化があります`)
63
+ assert.strictEqual(part['!クリア'], undefined, `${name}に!クリアがあります`)
64
+ }
65
+ })
66
+
67
+ it('分割ファイルの命令が plugin_system にマージされている', async () => {
68
+ for (const [name, part] of Object.entries(parts)) {
69
+ for (const key of Object.keys(part)) {
70
+ assert.strictEqual(PluginSystem[key], part[key], `${name}の『${key}』がマージされていません`)
71
+ }
72
+ }
73
+ })
74
+
75
+ it('分割してもプラグインは plugin_system のまま', async () => {
76
+ assert.strictEqual(PluginSystem.meta.value.pluginName, 'plugin_system')
77
+ await cmp('プラグイン一覧取得して「:」で配列結合して表示', 'plugin_system:plugin_math:plugin_promise:plugin_test:plugin_csv:plugin_toml')
78
+ })
79
+
80
+ // --- plugin_system_math.mts の疎通確認 ---
81
+ it('四則演算', async () => {
82
+ await cmp('3に4を掛けて表示', '12')
83
+ })
84
+ it('論理演算', async () => {
85
+ await cmp('もし、(1と1の論理AND)ならば「OK」を表示', 'OK')
86
+ })
87
+ it('ビット演算', async () => {
88
+ await cmp('5と3のANDを表示', '1')
89
+ })
90
+
91
+ // --- plugin_system_string.mts の疎通確認 ---
92
+ it('文字列処理', async () => {
93
+ await cmp('「なでしこ」の文字数を表示', '4')
94
+ })
95
+ it('置換・トリム', async () => {
96
+ await cmp('「 殿 」のトリムを表示', '殿')
97
+ })
98
+ it('文字変換', async () => {
99
+ await cmp('「abc」の大文字変換を表示', 'ABC')
100
+ })
101
+ it('指定形式', async () => {
102
+ await cmp('123を5でゼロ埋して表示', '00123')
103
+ })
104
+ it('文字種類', async () => {
105
+ await cmp('もし、「あ」のかなか判定ならば「OK」を表示', 'OK')
106
+ })
107
+
108
+ // --- plugin_system_array.mts の疎通確認 ---
109
+ it('配列操作', async () => {
110
+ await cmp('[1,2,3]を「-」で配列結合して表示', '1-2-3')
111
+ })
112
+ it('二次元配列処理', async () => {
113
+ const g = await new NakoCompiler().runAsync('A=[[3,1],[1,2]];Aの0を表ソート;Aを JSON変換して表示', 'main.nako3')
114
+ assert.strictEqual(g.log, '[[1,2],[3,1]]')
115
+ })
116
+
117
+ // --- plugin_system_datetime.mts の疎通確認 ---
118
+ it('日時処理(簡易)', async () => {
119
+ await cmp('「2024/01/01」の曜日を表示', '月')
120
+ })
121
+
122
+ // --- plugin_system_url.mts の疎通確認 ---
123
+ it('URLエンコード・デコード', async () => {
124
+ await cmp('「あ」をURLエンコードしてURLデコードして表示', 'あ')
125
+ })
126
+ it('BASE64', async () => {
127
+ await cmp('「なでしこ」をBASE64エンコードしてBASE64デコードして表示', 'なでしこ')
128
+ })
129
+ it('パス操作', async () => {
130
+ await cmp('「/a/b/c.txt」のファイル名抽出を表示', 'c.txt')
131
+ await cmp('「/a/b/c.txt」の拡張子抽出を表示', '.txt')
132
+ })
133
+
134
+ // --- plugin_system_types.mts の疎通確認 ---
135
+ it('型変換', async () => {
136
+ await cmp('「3.14」を文字列変換して表示', '3.14')
137
+ await cmp('「3.14」を整数変換して表示', '3')
138
+ await cmp('TYPEOF(123)を表示', 'number')
139
+ await cmp('3と4の5でRGBを表示', '#030405')
140
+ })
141
+
142
+ // --- plugin_system_json.mts の疎通確認 ---
143
+ it('JSON', async () => {
144
+ await cmp('[1,2,3]をJSON変換して表示', '[1,2,3]')
145
+ await cmp('「[1,2,3]」をJSON取得してJSON変換して表示', '[1,2,3]')
146
+ })
147
+
148
+ // --- plugin_system_regexp.mts の疎通確認 ---
149
+ it('正規表現', async () => {
150
+ await cmp('「abc123」を『/([a-z]+)(\\d+)/』で正規表現マッチして表示', 'abc123')
151
+ await cmp('「abc123」を『/([a-z]+)(\\d+)/』で正規表現マッチ;抽出文字列を「,」で配列結合して表示', 'abc,123')
152
+ })
153
+
154
+ // --- plugin_system_dict.mts の疎通確認 ---
155
+ it('辞書型変数の操作', async () => {
156
+ await cmp('A={"a":1,"b":2};Aの辞書キー列挙を「,」で配列結合して表示', 'a,b')
157
+ })
158
+ it('ハッシュ', async () => {
159
+ await cmp('A={"a":1,"b":2};Aのハッシュキー列挙を「,」で配列結合して表示', 'a,b')
160
+ })
161
+
162
+ // --- plugin_system_stdio.mts の疎通確認 ---
163
+ it('標準出力', async () => {
164
+ await cmp('「あ」と継続表示;「い」を表示', 'あい')
165
+ await cmp('「a」と「b」と「c」を連続表示', 'abc')
166
+ })
167
+
168
+ // --- plugin_system_timer.mts の疎通確認 ---
169
+ it('タイマー処理', async () => {
170
+ // 秒後で発行したタイマーIDが取得でき、タイマー停止できること
171
+ await cmp(
172
+ 'F=関数()\n' +
173
+ 'ここまで\n' +
174
+ 'Fを0.01秒後\n' +
175
+ 'もし、(対象>0)ならば「OK」を表示\n' +
176
+ '対象のタイマー停止',
177
+ 'OK')
178
+ })
179
+ })
@@ -477,6 +477,8 @@ describe('plugin_system_test', async () => {
477
477
  it('URLパラメータ解析', async () => {
478
478
  await cmp('「http://hoge.com/」のURLパラメータ解析してJSONエンコードして表示', '{}')
479
479
  await cmp('「https://nadesi.com/?a=3&b=5」のURLパラメータ解析;それ["a"]を表示;それ["b"]を表示。', '3\n5')
480
+ await cmp('「https://nadesi.com/?a=3=3&b=5」のURLパラメータ解析;それ["a"]を表示;それ["b"]を表示。', '3=3\n5')
481
+ await cmp('「https://nadesi.com/?a&b=5」のURLパラメータ解析;それ["a"]を表示;それ["b"]を表示。', '\n5')
480
482
  })
481
483
  it('助詞省略形のコマンド', async () => {
482
484
  await cmp('3が1以上。もし、そうなら「OK」と表示。', 'OK')
@@ -776,6 +778,10 @@ describe('plugin_system_test', async () => {
776
778
  await cmp('S=「💧🔥🍵」;Sの2から1文字削除して表示', '💧🍵')
777
779
  await cmp('S=「1💧3🔥5🍵」;Sの3から2文字削除して表示', '1💧5🍵')
778
780
  })
781
+ it('数字の文字数が0になる不具合 #2342', async () => {
782
+ await cmp('30の文字数を表示', '2')
783
+ await cmp('12345の文字数を表示', '5')
784
+ })
779
785
  it('左トリム', async () => {
780
786
  await cmp('S=「 \t💧🔥🍵」;Sを左トリムして表示', '💧🔥🍵')
781
787
  await cmp('S=「 ABC 」;Sを左トリムして「|」を追加して表示', 'ABC |')
@@ -25,7 +25,6 @@
25
25
  /* Modules */
26
26
  "module": "ESNext", /* Specify what module code is generated. */
27
27
  // "rootDir": "./", /* Specify the root folder within your source files. */
28
- "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
29
28
  "ignoreDeprecations": "6.0", /* TypeScript 6.0 の非推奨警告を抑制する */
30
29
  // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
31
30
  "paths": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nadesiko3",
3
- "version": "3.7.21",
3
+ "version": "3.7.22",
4
4
  "description": "Japanese Programming Language",
5
5
  "type": "module",
6
6
  "main": "src/index.mjs",
@@ -33,8 +33,10 @@
33
33
  "build:browsers": "browserslist > src/browsers.txt && node src/cnako3.mjs batch/build_browsers.nako3",
34
34
  "publish:desc": "node -e \"console.log('Please exec => npm run build && npm run test:all && npm publish && npm run publish:version')",
35
35
  "publish:version": "node src/cnako3.mjs batch/publish_version.nako3 && node src/cnako3.mjs batch/copy_core.nako3",
36
- "eslint": "eslint src/*.mts core/src/*.mts",
37
- "eslint:fix": "eslint . --ext mts --fix",
36
+ "lint": "oxlint src/*.mts core/src/*.mts",
37
+ "lint:fix": "oxlint src/*.mts core/src/*.mts --fix",
38
+ "eslint": "npm run lint",
39
+ "eslint:fix": "npm run lint:fix",
38
40
  "extlib:clean": "rm -f -r demo/extlib/*",
39
41
  "extlib:install": "node src/cnako3.mjs batch/download-extlib.nako3",
40
42
  "check_new_version": "node src/cnako3.mjs tools/check_new_version.nako3",
@@ -84,44 +86,38 @@
84
86
  "utils": "/utils"
85
87
  },
86
88
  "devDependencies": {
87
- "@eslint/js": "^9.39.3",
88
89
  "@types/fs-extra": "^11.0.4",
89
- "@types/node": "^26.0.0",
90
+ "@types/node": "^26.1.2",
90
91
  "@types/opener": "^1.4.3",
91
92
  "@types/shell-quote": "^1.7.5",
92
93
  "ace-builds": "^1.44.0",
93
94
  "body-parser": "^2.3.0",
94
- "browserslist": "^4.28.2",
95
+ "browserslist": "^4.28.7",
95
96
  "buffer": "^6.0.3",
96
97
  "chai": "^6.2.2",
97
98
  "cross-env": "^10.1.0",
98
99
  "esbuild": "0.28.1",
99
- "eslint": "^9.39.3",
100
- "eslint-plugin-import": "^2.32.0",
101
- "eslint-plugin-n": "^18.1.0",
102
- "eslint-plugin-promise": "^7.3.0",
103
- "express": "^5.2.1",
104
100
  "fetch-mock": "^12.6.0",
105
101
  "hotkeys-js": "^4.0.4",
106
102
  "module-alias": "^2.3.4",
107
103
  "multer": "^2.2.0",
108
- "npm-check-updates": "^22.2.3",
104
+ "npm-check-updates": "^23.0.0",
105
+ "oxlint": "^1.76.0",
109
106
  "prop-types": "^15.8.1",
110
- "react": "^19.2.7",
111
- "react-dom": "^19.2.7",
107
+ "react": "^19.2.8",
108
+ "react-dom": "^19.2.8",
112
109
  "testdouble": "^3.20.2",
113
- "typescript": "^6.0.3",
114
- "typescript-eslint": "^8.61.1",
110
+ "typescript": "^7.0.2",
115
111
  "util": "^0.12.5"
116
112
  },
117
113
  "dependencies": {
118
114
  "dayjs": "^1.11.21",
119
- "fs-extra": "^11.3.5",
115
+ "fs-extra": "^11.4.0",
120
116
  "html": "^1.0.0",
121
- "iconv-lite": "^0.7.2",
122
- "marked": "^18.0.5",
117
+ "iconv-lite": "^0.7.3",
118
+ "marked": "^18.0.7",
123
119
  "opener": "^1.5.2",
124
- "shell-quote": "^1.8.4",
125
- "smol-toml": "1.7.0"
120
+ "shell-quote": "^1.10.0",
121
+ "smol-toml": "1.7.1"
126
122
  }
127
123
  }
package/release/_hash.txt CHANGED
@@ -1,18 +1,18 @@
1
1
  command.json.js:
2
- md5(hex): e5d5d2cc46001d4a79a32888b14fde21
3
- sha256(hex): eb20417afc284ac062b79e9eb6c4c0c9741fd1e5cc78c9e48f1792e1e8014579
4
- sha256(base64): 6yBBevwoSsBit56etsTAyXQf0eXMeMnkjxeS4egBRXk=
5
- sha512(base64): K6yAgO2BR4MDfDFce3YyJUbfF3fJf1MEFbxD1HH4ZW/oodZlAYPPTwOxnGbzpAWGHknYprcLQspDoJdLy2kd2w==
2
+ md5(hex): faa8e3441a7148e276e9fb6968901a89
3
+ sha256(hex): a99e299bf395326dcd5757328b17efa171e3ec3d4bf502d13e3a95c3ba6713d5
4
+ sha256(base64): qZ4pm/OVMm3NV1cyixfvoXHj7D1L9QLRPjqVw7pnE9U=
5
+ sha512(base64): c0FxM+w92HXMBXvJTno5bPTFwMIRl+Z+13Fcg1oX8JkcQ8Kz2LnMjFCqpmsYzZzDI4pbhRCSKQ2KsIAtTianSA==
6
6
  edit_main.js:
7
- md5(hex): f1f1c0b8ef845ba98201948602238b7e
8
- sha256(hex): aeb4d7e6d28c26c76fc5c44377140b6feea18e7b0b3aafc7560160cb3d127162
9
- sha256(base64): rrTX5tKMJsdvxcRDdxQLb+6hjnsLOq/HVgFgyz0ScWI=
10
- sha512(base64): Z7ZtWJgmI+bCIRuwPYptMkHQzrzvvVjgMXY/y2plkxE94y+j2wfEczeTA0o2ax6MJAi1v7PY1m3LhNdPNCi3FQ==
7
+ md5(hex): 46bf139ef2c990050eb54fe39a75d7e4
8
+ sha256(hex): 9b93dcdce8090cb52210de552eef220cb2240f8cde969f97e8066d0767686a0b
9
+ sha256(base64): m5Pc3OgJDLUiEN5VLu8iDLIkD4zelp+X6AZtB2doags=
10
+ sha512(base64): 2dBmulrKAMmAZMAaqYexhp6NKi436hDwGhmaKHLhyBVb1cR2HKKJHzc5V/w4D5Ikj0F1KWh/EnLOD6hCJo7XWQ==
11
11
  editor.js:
12
- md5(hex): f1f1c0b8ef845ba98201948602238b7e
13
- sha256(hex): aeb4d7e6d28c26c76fc5c44377140b6feea18e7b0b3aafc7560160cb3d127162
14
- sha256(base64): rrTX5tKMJsdvxcRDdxQLb+6hjnsLOq/HVgFgyz0ScWI=
15
- sha512(base64): Z7ZtWJgmI+bCIRuwPYptMkHQzrzvvVjgMXY/y2plkxE94y+j2wfEczeTA0o2ax6MJAi1v7PY1m3LhNdPNCi3FQ==
12
+ md5(hex): 46bf139ef2c990050eb54fe39a75d7e4
13
+ sha256(hex): 9b93dcdce8090cb52210de552eef220cb2240f8cde969f97e8066d0767686a0b
14
+ sha256(base64): m5Pc3OgJDLUiEN5VLu8iDLIkD4zelp+X6AZtB2doags=
15
+ sha512(base64): 2dBmulrKAMmAZMAaqYexhp6NKi436hDwGhmaKHLhyBVb1cR2HKKJHzc5V/w4D5Ikj0F1KWh/EnLOD6hCJo7XWQ==
16
16
  plugin_caniuse.js:
17
17
  md5(hex): f0e9712eeeeb303ae6f9795e6401879c
18
18
  sha256(hex): 3031bf295c93909ef8d45a164f6d1758ffa56624e643dc7052018055066c8527
@@ -34,10 +34,10 @@ plugin_keigo.js:
34
34
  sha256(base64): 1IZs3kTk2nHl90N3Fyq1uFr8EpWmDAgfbXwkUl9APg0=
35
35
  sha512(base64): u067+CeBvMb6+oINFY9Wz77GBk4NSxS2+k35GJ3RsFFmphJliwzwmV2ceID0gZ4mbjJ0xJHQX9WIypiyI6yfdA==
36
36
  plugin_markup.js:
37
- md5(hex): aa1d89920db475a6385e2418ebe4ade4
38
- sha256(hex): b0dd3456947bf6dbf71652901b8e612ebc888b01cec02c7117c0391781d0411e
39
- sha256(base64): sN00VpR79tv3FlKQG45hLryIiwHOwCxxF8A5F4HQQR4=
40
- sha512(base64): FR2TUWrnt8dT/Mc+qCv3geeaY4G4Ts48yx6/sxPD6vlw9W+E/uceYxuGHTbrsMmWPX6AUaxG1PLsTplTDh3SWw==
37
+ md5(hex): 92464090d6e124460ee40465a16526de
38
+ sha256(hex): dec7ca9a136ac2757b70d3c2e4a000053bb65ab59fe687b2b73a4ffeaee61b4b
39
+ sha256(base64): 3sfKmhNqwnV7cNPC5KAABTu2WrWf5oeytzpP/q7mG0s=
40
+ sha512(base64): 6xP6LjhqTkVmpYoRnQDfEzj0gPVyeT1fyj42K6MQIiRW958NhAVgqMUZVXGYb1T4RzYNSyBArPg+384gh+VFNw==
41
41
  plugin_three.js:
42
42
  md5(hex): 5fa1fba6c48576ba6046e9302b3bcf89
43
43
  sha256(hex): e2b2c54d9674837d51cc91d032e3aa9f2a1cc8fbc11b6be503649a1cccfe08cb
@@ -54,27 +54,27 @@ plugin_webworker.js:
54
54
  sha256(base64): RqC7JMHY8dBlIFfpNI6sobJqhX8P/Jk+kHCuaDYJwEU=
55
55
  sha512(base64): 6UHX2dgMPRY4BuIxLXaERKaA8Wg5eK2pWy+OysU0/+gt2E15M7K5Vr8+4CQt6hylWnmzmJQJfgObIr+yjW5kPw==
56
56
  plugin_weykturtle3d.js:
57
- md5(hex): a9c7efe13cbc4645bf04a1718c7e3790
58
- sha256(hex): b323c29296f4ff4fbac6ba6584e69a36240f2d75d4448b4b948c0ab3f849c6ed
59
- sha256(base64): syPCkpb0/0+6xrplhOaaNiQPLXXURItLlIwKs/hJxu0=
60
- sha512(base64): +PdMgS30v+ECdqzVmHPPTpEVku7/jUC5htY8edFgkIOxtWfaMv7yHj/3xOPOwWjgyoO0g7sciMX0nBEb1gxBkA==
57
+ md5(hex): b7ac59ade31110bfba8f799daa02bc7e
58
+ sha256(hex): 1060852e01e752d4b92bad2bcc31e6b1aa9519691353774c4c5fef827f6f655c
59
+ sha256(base64): EGCFLgHnUtS5K60rzDHmsaqVGWkTU3dMTF/vgn9vZVw=
60
+ sha512(base64): JQIX23cLX+Y7p+/4aLM/OjRlKneRpdihybBtRa31O/dbbeVdCa3Xrx0PE7ugpRXMGAZr0sYQpLraz6YjDYswVw==
61
61
  version.js:
62
- md5(hex): 2512904f680ea30117b3c0d4f785d717
63
- sha256(hex): 1f22f38ae06122cd802f1f4d6bfdd782748520faa9b012d9915982ba8edc7154
64
- sha256(base64): HyLziuBhIs2ALx9Na/3XgnSFIPqpsBLZkVmCuo7ccVQ=
65
- sha512(base64): M3Rm07ZpkJhUMk1nNrCJyNS+qey2ER7ZuxazBFp90RJgDtvsv3SPgPlIGec8rE4cTACBcoM2S0WgR096Q612Gw==
62
+ md5(hex): 41b86b0801dfc711ea606531eddb0339
63
+ sha256(hex): 2b49524c8445d629cbccffb62cdd905d127478f3835dafbf307b69c00b4092af
64
+ sha256(base64): K0lSTIRF1inLzP+2LN2QXRJ0ePODXa+/MHtpwAtAkq8=
65
+ sha512(base64): GhVQCDSP93IK1Zhq/cfq+7uT29huFTrI/z0vfx2xbkkO69k9eCazVIo6IZ7DfCyFcyTwWnKho2E9E1KeU/eqUA==
66
66
  version_main.js:
67
- md5(hex): 2512904f680ea30117b3c0d4f785d717
68
- sha256(hex): 1f22f38ae06122cd802f1f4d6bfdd782748520faa9b012d9915982ba8edc7154
69
- sha256(base64): HyLziuBhIs2ALx9Na/3XgnSFIPqpsBLZkVmCuo7ccVQ=
70
- sha512(base64): M3Rm07ZpkJhUMk1nNrCJyNS+qey2ER7ZuxazBFp90RJgDtvsv3SPgPlIGec8rE4cTACBcoM2S0WgR096Q612Gw==
67
+ md5(hex): 41b86b0801dfc711ea606531eddb0339
68
+ sha256(hex): 2b49524c8445d629cbccffb62cdd905d127478f3835dafbf307b69c00b4092af
69
+ sha256(base64): K0lSTIRF1inLzP+2LN2QXRJ0ePODXa+/MHtpwAtAkq8=
70
+ sha512(base64): GhVQCDSP93IK1Zhq/cfq+7uT29huFTrI/z0vfx2xbkkO69k9eCazVIo6IZ7DfCyFcyTwWnKho2E9E1KeU/eqUA==
71
71
  wnako3.js:
72
- md5(hex): 8c81e731cd0409d98326b7da1f0df49c
73
- sha256(hex): 54e11ab61036cd5a66fb7abc8dbbcc8bc28232de62eaba7c3dc499a56abef7e3
74
- sha256(base64): VOEathA2zVpm+3q8jbvMi8KCMt5i6rp8PcSZpWq+9+M=
75
- sha512(base64): 8aGGhpgYP+J5fsjZOLktHXECl4Nhcxsvo/wqB9IvVe8NQMhLpdBOLA3rB8+o0vqh+OZDv7uw1Qr/Wfome9h6ZA==
72
+ md5(hex): ef3fa40bba0e4dd07f1158b5d2d1813a
73
+ sha256(hex): c21494bcc304879f67bd3811ffe437049fce6e4ac6a517a678bdab94f913e9a2
74
+ sha256(base64): whSUvMMEh59nvTgR/+Q3BJ/ObkrGpRemeL2rlPkT6aI=
75
+ sha512(base64): WaY2b6SGEQaSG5qB5rWNWtAdBCWBxOoRrwxKkEVG5F1ThVqkOPF+rta7aCQTKMPtMNCnJ/bPMsldRUFmEbgFZA==
76
76
  wnako3webworker.js:
77
- md5(hex): f1f8dc85578822aaf4266df1cc1d6eaf
78
- sha256(hex): 46fc5b5f19d196d91bb4188e9f2a226d933367bd2ea18e10da9c2cc4ea9bd0b1
79
- sha256(base64): RvxbXxnRltkbtBiOnyoibZMzZ70uoY4Q2pwsxOqb0LE=
80
- sha512(base64): RDZosl0hzFRl24YxNfY3n8+WRmf3aHCfjJ8lrZ0VmsQZLop+g4ssGaahGn+RNz8Ih3Ab8Uy7oF0yxHBWtVmiYA==
77
+ md5(hex): 844a71b83975cc72fddac0a5b92a6494
78
+ sha256(hex): 6a4b2c0fa23f7f20606c49b75fc6c283b3a970428ede2627f91b39b689717520
79
+ sha256(base64): akssD6I/fyBgbEm3X8bCg7OpcEKO3iYn+Rs5tolxdSA=
80
+ sha512(base64): ydir+VI4OrubEDOH3E821m4NkqAdIGPeY1C8DwyTyzCTgLTgrWAw2wxkeEEm5Fo9cfuLIisc4KRLuORJyq02JQ==