nadesiko3 3.3.13 → 3.3.14
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/README.md +12 -0
- package/demo/nako3/aaa/bbb/ccc.nako3 +2 -0
- package/demo/nako3/aaa/p1.nako3 +4 -0
- package/demo/nako3/aaa.nako3 +5 -0
- package/package.json +1 -1
- package/release/_hash.txt +8 -8
- package/release/_script-tags.txt +14 -14
- package/release/stats.json +1 -1
- package/release/version.js +1 -1
- package/release/wnako3.js +1 -1
- package/src/cnako3mod.mjs +64 -22
- package/src/nako3.mjs +19 -20
- package/src/nako_gen.mjs +25 -33
- package/src/nako_version.mjs +2 -2
- package/src/plugin_node.mjs +12 -10
- package/src/wnako3.mjs +38 -15
- package/tools/nako3edit/run.mjs +1 -1
package/src/cnako3mod.mjs
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
/**
|
|
3
2
|
* コマンドライン版のなでしこ3をモジュールとして定義
|
|
4
3
|
* 実際には cnako3.js から読み込まれる
|
|
5
4
|
*/
|
|
6
5
|
import fs from 'fs'
|
|
7
6
|
import { exec } from 'child_process'
|
|
8
|
-
import path from 'path'
|
|
7
|
+
import path, { resolve } from 'path'
|
|
9
8
|
import { NakoCompiler } from './nako3.mjs'
|
|
10
9
|
import PluginNode from './plugin_node.mjs'
|
|
11
10
|
import { NakoImportError } from './nako_errors.mjs'
|
|
@@ -23,7 +22,7 @@ export class CNako3 extends NakoCompiler {
|
|
|
23
22
|
super({ useBasicPlugin: true })
|
|
24
23
|
this.silent = false
|
|
25
24
|
if (!opts.nostd) {
|
|
26
|
-
this.addPluginFile('PluginNode', path.join(__dirname, 'plugin_node.
|
|
25
|
+
this.addPluginFile('PluginNode', path.join(__dirname, 'plugin_node.mjs'), PluginNode)
|
|
27
26
|
}
|
|
28
27
|
this.__varslist[0]['ナデシコ種類'] = 'cnako3'
|
|
29
28
|
}
|
|
@@ -61,12 +60,23 @@ export class CNako3 extends NakoCompiler {
|
|
|
61
60
|
|
|
62
61
|
/**
|
|
63
62
|
* コマンドライン引数を解析
|
|
64
|
-
* @returns {{
|
|
63
|
+
* @returns {{
|
|
64
|
+
* warn: boolean,
|
|
65
|
+
* debug: boolean,
|
|
66
|
+
* compile: any | boolean,
|
|
67
|
+
* test: any | boolean,
|
|
68
|
+
* one_liner: any | boolean,
|
|
69
|
+
* trace: any | boolean,
|
|
70
|
+
* run: any | boolean,
|
|
71
|
+
* repl: any | boolean,
|
|
72
|
+
* source: any | string,
|
|
73
|
+
* mainfile: any | string,
|
|
74
|
+
* }}
|
|
65
75
|
*/
|
|
66
76
|
checkArguments () {
|
|
67
77
|
const app = this.registerCommands()
|
|
68
78
|
|
|
69
|
-
/** @type {import('./nako_logger').LogLevel} */
|
|
79
|
+
/** @type {import('./nako_logger.mjs').LogLevel} */
|
|
70
80
|
let logLevel = 'error'
|
|
71
81
|
if (app.trace) {
|
|
72
82
|
logLevel = 'trace'
|
|
@@ -99,21 +109,23 @@ export class CNako3 extends NakoCompiler {
|
|
|
99
109
|
}
|
|
100
110
|
args.mainfile = app.args[0]
|
|
101
111
|
args.output = app.output
|
|
112
|
+
|
|
113
|
+
// todo: ESModule 対応の '.mjs' のコードを履く #1217
|
|
114
|
+
const ext = '.js'
|
|
102
115
|
if (/\.(nako|nako3|txt|bak)$/.test(args.mainfile)) {
|
|
103
116
|
if (!args.output) {
|
|
104
117
|
if (args.test) {
|
|
105
|
-
args.output = args.mainfile.replace(/\.(nako|nako3)$/, '.spec
|
|
118
|
+
args.output = args.mainfile.replace(/\.(nako|nako3)$/, '.spec' + ext)
|
|
106
119
|
} else {
|
|
107
|
-
|
|
108
|
-
args.output = args.mainfile.replace(/\.(nako|nako3)$/, '.js')
|
|
120
|
+
args.output = args.mainfile.replace(/\.(nako|nako3)$/, ext)
|
|
109
121
|
}
|
|
110
122
|
}
|
|
111
123
|
} else {
|
|
112
124
|
if (!args.output) {
|
|
113
125
|
if (args.test) {
|
|
114
|
-
args.output = args.mainfile + '.spec
|
|
126
|
+
args.output = args.mainfile + '.spec' + ext
|
|
115
127
|
} else {
|
|
116
|
-
args.output = args.mainfile +
|
|
128
|
+
args.output = args.mainfile + ext
|
|
117
129
|
}
|
|
118
130
|
}
|
|
119
131
|
args.mainfile += '.nako3'
|
|
@@ -201,6 +213,28 @@ export class CNako3 extends NakoCompiler {
|
|
|
201
213
|
const jscode = this.compileStandalone(src, this.filename, isTest)
|
|
202
214
|
console.log(opt.output)
|
|
203
215
|
fs.writeFileSync(opt.output, jscode, 'utf-8')
|
|
216
|
+
|
|
217
|
+
/*
|
|
218
|
+
// 実行に必要なファイルをコピー
|
|
219
|
+
const nakoRuntime = __dirname
|
|
220
|
+
const outRuntime = path.join(path.dirname(opt.output), 'nako3runtime')
|
|
221
|
+
if (!fs.existsSync(outRuntime)) { fs.mkdirSync(outRuntime) }
|
|
222
|
+
for (let mod of ['nako_version.mjs', 'nako_errors.mjs', 'plugin_node.mjs']) {
|
|
223
|
+
fs.copyFileSync(path.join(nakoRuntime, mod), path.join(outRuntime, mod))
|
|
224
|
+
}
|
|
225
|
+
// todo: 必要に応じてnode_modulesをコピー (時間が掛かりすぎるのでコピーしない)
|
|
226
|
+
const dstModule = path.join(path.dirname(opt.output), 'node_modules')
|
|
227
|
+
const orgModule = path.join(__dirname, '..', 'node_modules')
|
|
228
|
+
if (!fs.existsSync(dstModule)) {
|
|
229
|
+
fs.mkdirSync(dstModule)
|
|
230
|
+
fse.copySync(path.join(orgModule), path.join(dstModule))
|
|
231
|
+
}
|
|
232
|
+
// or 以下のコピーだと依存ファイルがコピーされない package.jsonを見てコピーする必要がある
|
|
233
|
+
for (let mod of ['fs-extra', 'iconv-lite', 'opener', 'clipboardy', 'sendkeys-js']) {
|
|
234
|
+
fse.copySync(path.join(orgModule, mod), path.join(dstModule, mod))
|
|
235
|
+
}
|
|
236
|
+
*/
|
|
237
|
+
|
|
204
238
|
if (opt.run) {
|
|
205
239
|
exec(`node ${opt.output}`, function (err, stdout, stderr) {
|
|
206
240
|
if (err) { console.log('[ERROR]', stderr) }
|
|
@@ -321,7 +355,7 @@ export class CNako3 extends NakoCompiler {
|
|
|
321
355
|
/** @type {string[]} */
|
|
322
356
|
const log = []
|
|
323
357
|
const tools = {}
|
|
324
|
-
tools.resolvePath = (name, token) => {
|
|
358
|
+
tools.resolvePath = (name, token, fromFile) => {
|
|
325
359
|
// JSプラグインのパスを解決する
|
|
326
360
|
if (/\.(js|mjs)(\.txt)?$/.test(name) || /^[^.]*$/.test(name)) {
|
|
327
361
|
const jspath = CNako3.findJSPluginFile(name, this.filename, __dirname, log)
|
|
@@ -336,28 +370,36 @@ export class CNako3 extends NakoCompiler {
|
|
|
336
370
|
return { filePath: path.resolve(name), type: 'nako3' }
|
|
337
371
|
} else {
|
|
338
372
|
// filename が undefined のとき token.file が undefined になる。
|
|
339
|
-
if (token.file === undefined) {
|
|
340
|
-
|
|
341
|
-
}
|
|
342
|
-
return { filePath: path.resolve(path.join(path.dirname(token.file), name)), type: 'nako3' }
|
|
373
|
+
if (token.file === undefined) { throw new Error('ファイル名を指定してください。') }
|
|
374
|
+
const dir = path.dirname(fromFile)
|
|
375
|
+
return { filePath: path.resolve(path.join(dir, name)), type: 'nako3' }
|
|
343
376
|
}
|
|
344
377
|
}
|
|
345
378
|
return { filePath: name, type: 'invalid' }
|
|
346
379
|
}
|
|
347
380
|
tools.readNako3 = (name, token) => {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
|
|
381
|
+
// ファイルチェックだけ先に実行
|
|
382
|
+
if (!fs.existsSync(name)) {
|
|
383
|
+
throw new NakoImportError(`ファイル ${name} が存在しません。`, token.file, token.line)
|
|
384
|
+
}
|
|
385
|
+
// 非同期で読み込む
|
|
386
|
+
const loader = {task: null}
|
|
387
|
+
loader.task = (new Promise((resolve, reject) => {
|
|
388
|
+
fs.readFile(name, {encoding: 'utf-8'}, (err, data) => {
|
|
389
|
+
if (err) { return reject(err) }
|
|
390
|
+
resolve(data)
|
|
391
|
+
})
|
|
392
|
+
}))
|
|
393
|
+
return loader
|
|
352
394
|
}
|
|
353
395
|
tools.readJs = (filePath, token) => {
|
|
354
|
-
const
|
|
396
|
+
const loader = {task: null}
|
|
355
397
|
if (process.platform === 'win32') {
|
|
356
398
|
if (filePath.substring(1, 3) === ':\\') {
|
|
357
399
|
filePath = 'file://' + filePath
|
|
358
400
|
}
|
|
359
401
|
}
|
|
360
|
-
|
|
402
|
+
loader.task = (
|
|
361
403
|
new Promise((resolve, reject) => {
|
|
362
404
|
import(filePath).then((mod) => {
|
|
363
405
|
// プラグインは export default で宣言されている? (moduleプラグインの場合)
|
|
@@ -369,7 +411,7 @@ export class CNako3 extends NakoCompiler {
|
|
|
369
411
|
})
|
|
370
412
|
})
|
|
371
413
|
)
|
|
372
|
-
return
|
|
414
|
+
return loader
|
|
373
415
|
}
|
|
374
416
|
return tools
|
|
375
417
|
}
|
package/src/nako3.mjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
/**
|
|
3
2
|
* nadesiko v3
|
|
4
3
|
*/
|
|
@@ -177,18 +176,20 @@ export class NakoCompiler {
|
|
|
177
176
|
|
|
178
177
|
/**
|
|
179
178
|
* プログラムが依存するファイルを再帰的に取得する。
|
|
180
|
-
* -
|
|
181
|
-
* -
|
|
182
|
-
*
|
|
183
|
-
* - readNako3はソースコードを返す。readJsはrequireあるいはevalする関数を返す。
|
|
179
|
+
* - 依存するファイルがJavaScriptファイルの場合、そのファイルを実行して評価結果をthis.addPluginFileに渡す。
|
|
180
|
+
* - 依存するファイルがなでしこ言語の場合、ファイルの中身を取得して変数に保存し、再帰する。
|
|
181
|
+
*
|
|
184
182
|
* @param {string} code
|
|
185
183
|
* @param {string} filename
|
|
186
184
|
* @param {string} preCode
|
|
187
185
|
* @param {{
|
|
188
|
-
* resolvePath: (name: string, token: TokenWithSourceMap) => { type: 'nako3' | 'js' | 'invalid', filePath: string }
|
|
189
|
-
* readNako3: (filePath: string, token: TokenWithSourceMap) => {
|
|
190
|
-
* readJs: (filePath: string, token: TokenWithSourceMap) => {
|
|
191
|
-
* }} tools
|
|
186
|
+
* resolvePath: (name: string, token: TokenWithSourceMap, fromFile: string) => { type: 'nako3' | 'js' | 'invalid', filePath: string }
|
|
187
|
+
* readNako3: (filePath: string, token: TokenWithSourceMap) => { task: Promise<string> }
|
|
188
|
+
* readJs: (filePath: string, token: TokenWithSourceMap) => { task: Promise<() => object> }
|
|
189
|
+
* }} tools - 実行環境 (ブラウザ or Node.js) によって外部ファイルの取得・実行方法は異なるため、引数でそれらを行う関数を受け取る。
|
|
190
|
+
* - resolvePath は指定した名前をもつファイルを検索し、正規化されたファイル名を返す関数。返されたファイル名はreadNako3かreadJsの引数になる。
|
|
191
|
+
* - readNako3は指定されたファイルの中身を返す関数。
|
|
192
|
+
* - readJsは指定したファイルをJavaScriptのプログラムとして実行し、`export default` でエクスポートされた値を返す関数。
|
|
192
193
|
* @returns {Promise<unknown> | void}
|
|
193
194
|
* @protected
|
|
194
195
|
*/
|
|
@@ -200,10 +201,12 @@ export class NakoCompiler {
|
|
|
200
201
|
const loadJS = (item, tasks) => {
|
|
201
202
|
// jsならプラグインとして読み込む。(ESMでは必ず動的に読む)
|
|
202
203
|
const obj = tools.readJs(item.filePath, item.firstToken)
|
|
203
|
-
tasks.push(obj.
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
204
|
+
tasks.push(obj.task.then((res) => {
|
|
205
|
+
const pluginFuncs = res()
|
|
206
|
+
this.addPluginFile(item.value, item.filePath, pluginFuncs, false)
|
|
207
|
+
dependencies[item.filePath].funclist = pluginFuncs
|
|
208
|
+
dependencies[item.filePath].addPluginFile = () => { this.addPluginFile(item.value, item.filePath, pluginFuncs, false) }
|
|
209
|
+
}))
|
|
207
210
|
}
|
|
208
211
|
const loadNako3 = (item, tasks) => {
|
|
209
212
|
// nako3ならファイルを読んでdependenciesに保存する。
|
|
@@ -221,15 +224,11 @@ export class NakoCompiler {
|
|
|
221
224
|
const funclist = {}
|
|
222
225
|
NakoLexer.preDefineFunc(cloneAsJSON(tokens), this.logger, funclist)
|
|
223
226
|
dependencies[item.filePath].funclist = funclist
|
|
224
|
-
|
|
225
227
|
// 再帰
|
|
226
228
|
return loadRec(code, item.filePath, '')
|
|
227
229
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
} else {
|
|
231
|
-
tasks.push(content.value.then((res) => registerFile(res)))
|
|
232
|
-
}
|
|
230
|
+
// 取り込み構文における問題を減らすため、必ず非同期でプログラムを読み込む仕様とした #1219
|
|
231
|
+
tasks.push(content.task.then((res) => registerFile(res)))
|
|
233
232
|
}
|
|
234
233
|
/** @param {string} code @param {string} filename @param {string} preCode @returns {Promise<unknown> | void} */
|
|
235
234
|
const loadRec = (code, filename, preCode) => {
|
|
@@ -238,7 +237,7 @@ export class NakoCompiler {
|
|
|
238
237
|
// 取り込みが必要な情報一覧を調べる(トークン分割して、取り込みタグを得る)
|
|
239
238
|
const tags = NakoCompiler.listRequireStatements(compiler.rawtokenize(code, 0, filename, preCode))
|
|
240
239
|
// パスを解決する
|
|
241
|
-
const tagsResolvePath = tags.map((v) => ({ ...v, ...tools.resolvePath(v.value, v.firstToken) }))
|
|
240
|
+
const tagsResolvePath = tags.map((v) => ({ ...v, ...tools.resolvePath(v.value, v.firstToken, filename) }))
|
|
242
241
|
// 取り込み開始
|
|
243
242
|
for (const item of tagsResolvePath) {
|
|
244
243
|
// 2回目以降の読み込み
|
package/src/nako_gen.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* file: nako_gen.js
|
|
3
2
|
* パーサーが生成した中間オブジェクトを実際のJavaScriptのコードに変換する。
|
|
4
3
|
* なお速度優先で忠実にJavaScriptのコードを生成する。
|
|
5
4
|
*/
|
|
@@ -7,12 +6,6 @@
|
|
|
7
6
|
import { NakoSyntaxError, NakoError, NakoRuntimeError } from './nako_errors.mjs'
|
|
8
7
|
import { NakoLexer } from './nako_lexer.mjs'
|
|
9
8
|
import nakoVersion from './nako_version.mjs'
|
|
10
|
-
const isIE11 = () => {
|
|
11
|
-
if (typeof(window) == 'object' && window.navigator && window.navigator.userAgent) {
|
|
12
|
-
return (window.navigator.userAgent.indexOf('MSIE') >= 0)
|
|
13
|
-
}
|
|
14
|
-
return false
|
|
15
|
-
}
|
|
16
9
|
|
|
17
10
|
// なでしこで定義した関数の開始コードと終了コード
|
|
18
11
|
const topOfFunction = '(function(){\n'
|
|
@@ -1546,7 +1539,7 @@ export class NakoGen {
|
|
|
1546
1539
|
|
|
1547
1540
|
|
|
1548
1541
|
/**
|
|
1549
|
-
* @param {import('./nako3')} com
|
|
1542
|
+
* @param {import('./nako3.mjs').NakoCompiler} com
|
|
1550
1543
|
* @param {Ast} ast
|
|
1551
1544
|
* @param {boolean | string} isTest 文字列なら1つのテストだけを実行する
|
|
1552
1545
|
*/
|
|
@@ -1573,21 +1566,19 @@ export function generateJS (com, ast, isTest) {
|
|
|
1573
1566
|
}
|
|
1574
1567
|
// async method
|
|
1575
1568
|
if (gen.numAsyncFn > 0) {
|
|
1576
|
-
|
|
1577
|
-
if (canAsync) {
|
|
1578
|
-
js = `
|
|
1569
|
+
js = `
|
|
1579
1570
|
// <nadesiko3::gen::async>
|
|
1580
1571
|
(async () => { // async::main
|
|
1581
1572
|
${js}
|
|
1582
1573
|
}).call(this).catch(err => {
|
|
1583
|
-
if (
|
|
1584
|
-
err
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1574
|
+
if (typeof(NakoRuntimeError) === 'undefined') { NakoRuntimeError = this.NakoRuntimeError }
|
|
1575
|
+
if (!(err instanceof NakoRuntimeError)) {
|
|
1576
|
+
err = new NakoRuntimeError(err, this.__varslist[0].line);
|
|
1577
|
+
}
|
|
1578
|
+
this.logger.error(err);
|
|
1579
|
+
throw err;
|
|
1588
1580
|
}); // async::main
|
|
1589
1581
|
// <nadesiko3::gen::async>\n`
|
|
1590
|
-
}
|
|
1591
1582
|
}
|
|
1592
1583
|
|
|
1593
1584
|
// デバッグメッセージ
|
|
@@ -1595,36 +1586,37 @@ throw err;
|
|
|
1595
1586
|
// todo: 将来的に mjs のコードを履くように修正する
|
|
1596
1587
|
const standaloneJSCode = `\
|
|
1597
1588
|
// <standaloneCode>
|
|
1589
|
+
// 将来的に ESModule に対応する #1217
|
|
1590
|
+
// import path from 'path'
|
|
1591
|
+
// import PluginNode from './nako3runtime/plugin_node.mjs'
|
|
1592
|
+
// import {NakoRuntimeError} from './nako3runtime/nako_errors.mjs'
|
|
1593
|
+
|
|
1598
1594
|
const path = require('path')
|
|
1599
|
-
const nakoVersion = ${JSON.stringify(nakoVersion)};
|
|
1600
1595
|
${NakoError.toString()}
|
|
1601
|
-
${NakoRuntimeError.toString()}
|
|
1602
|
-
|
|
1603
|
-
|
|
1596
|
+
${NakoRuntimeError.toString()}
|
|
1597
|
+
const nakoVersion = ${JSON.stringify(nakoVersion)};
|
|
1598
|
+
const self = this
|
|
1599
|
+
self.logger = {
|
|
1604
1600
|
error: (message) => { console.error(message) },
|
|
1605
1601
|
send: (level, message) => { console.log(message) },
|
|
1606
1602
|
};
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1603
|
+
self.__varslist = [{}, {}, {}];
|
|
1604
|
+
self.__vars = self.__varslist[2];
|
|
1605
|
+
self.__module = {};
|
|
1606
|
+
self.__locals = {};
|
|
1607
|
+
self.__genMode = 'sync';
|
|
1612
1608
|
try {
|
|
1613
1609
|
${gen.getVarsCode()}
|
|
1614
1610
|
${js}
|
|
1615
1611
|
} catch (err) {
|
|
1616
1612
|
if (!(err instanceof NakoRuntimeError)) {
|
|
1617
|
-
err = new NakoRuntimeError(err, __varslist[0].line);
|
|
1613
|
+
err = new NakoRuntimeError(err, self.__varslist[0].line);
|
|
1618
1614
|
}
|
|
1619
|
-
|
|
1615
|
+
self.logger.error(err);
|
|
1620
1616
|
throw err;
|
|
1621
1617
|
}
|
|
1622
|
-
//
|
|
1623
|
-
} // end of __nako3safunc function
|
|
1624
|
-
__nako3safunc();
|
|
1625
1618
|
// </standaloneCode>
|
|
1626
|
-
`
|
|
1627
|
-
|
|
1619
|
+
`
|
|
1628
1620
|
return {
|
|
1629
1621
|
// なでしこの実行環境ありの場合
|
|
1630
1622
|
runtimeEnv: js,
|
package/src/nako_version.mjs
CHANGED
package/src/plugin_node.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* file: plugin_node.
|
|
2
|
+
* file: plugin_node.mjs
|
|
3
3
|
* node.js のためのプラグイン
|
|
4
4
|
*/
|
|
5
5
|
import fs from 'fs'
|
|
@@ -11,9 +11,8 @@ import iconv from 'iconv-lite'
|
|
|
11
11
|
import opener from 'opener'
|
|
12
12
|
import clipboardy from 'clipboardy'
|
|
13
13
|
import assert from 'assert'
|
|
14
|
-
//
|
|
15
|
-
import
|
|
16
|
-
import { stdin as input, stdout as output } from 'process'
|
|
14
|
+
// 「標準入力取得時」「尋」で利用
|
|
15
|
+
import readline from 'readline'
|
|
17
16
|
// ハッシュ関数で利用
|
|
18
17
|
import crypto from 'crypto'
|
|
19
18
|
import os from 'os'
|
|
@@ -585,11 +584,15 @@ export default {
|
|
|
585
584
|
josi: [['と', 'を']],
|
|
586
585
|
pure: true,
|
|
587
586
|
asyncFn: true,
|
|
588
|
-
fn:
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
587
|
+
fn: function (msg, sys) {
|
|
588
|
+
return new Promise((resolve, _reject) => {
|
|
589
|
+
const rl = readline.createInterface(process.stdin, process.stdout)
|
|
590
|
+
rl.question(msg, (buf) => {
|
|
591
|
+
rl.close()
|
|
592
|
+
if (buf && buf.match(/^[0-9.]+$/)) { buf = parseFloat(buf) }
|
|
593
|
+
resolve(buf)
|
|
594
|
+
})
|
|
595
|
+
})
|
|
593
596
|
}
|
|
594
597
|
},
|
|
595
598
|
// @テスト
|
|
@@ -598,7 +601,6 @@ export default {
|
|
|
598
601
|
josi: [['と'], ['が']],
|
|
599
602
|
pure: true,
|
|
600
603
|
fn: function (a, b, sys) {
|
|
601
|
-
|
|
602
604
|
assert.strictEqual(a, b)
|
|
603
605
|
}
|
|
604
606
|
},
|
package/src/wnako3.mjs
CHANGED
|
@@ -53,17 +53,15 @@ class WebNakoCompiler extends NakoCompiler {
|
|
|
53
53
|
// eslint-disable-next-line no-prototype-builtins
|
|
54
54
|
if (localFiles.hasOwnProperty(filePath)) {
|
|
55
55
|
return {
|
|
56
|
-
|
|
57
|
-
value: () => {
|
|
56
|
+
task: (async () => () => {
|
|
58
57
|
// eslint-disable-next-line no-new-func
|
|
59
58
|
Function(localFiles[filePath])()
|
|
60
59
|
return {}
|
|
61
|
-
}
|
|
60
|
+
})()
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
63
|
return {
|
|
65
|
-
|
|
66
|
-
value: (async () => {
|
|
64
|
+
task: (async () => {
|
|
67
65
|
const res = await fetch(filePath)
|
|
68
66
|
if (!res.ok) {
|
|
69
67
|
throw new NakoImportError(`ファイル『${filePath}』のダウンロードに失敗しました: ${res.status} ${res.statusText}`, token.file, token.line)
|
|
@@ -93,11 +91,10 @@ class WebNakoCompiler extends NakoCompiler {
|
|
|
93
91
|
readNako3: (filePath, token) => {
|
|
94
92
|
// eslint-disable-next-line no-prototype-builtins
|
|
95
93
|
if (localFiles.hasOwnProperty(filePath)) {
|
|
96
|
-
return {
|
|
94
|
+
return {task: (async () => { return localFiles[filePath] })}
|
|
97
95
|
}
|
|
98
96
|
return {
|
|
99
|
-
|
|
100
|
-
value: (async () => {
|
|
97
|
+
task: (async () => {
|
|
101
98
|
const res = await fetch(filePath)
|
|
102
99
|
if (!res.ok) {
|
|
103
100
|
throw new NakoImportError(`ファイル ${filePath} のダウンロードに失敗しました: ${res.status} ${res.statusText}`, token.file, token.line)
|
|
@@ -106,7 +103,7 @@ class WebNakoCompiler extends NakoCompiler {
|
|
|
106
103
|
})()
|
|
107
104
|
}
|
|
108
105
|
},
|
|
109
|
-
resolvePath: (name, token) => {
|
|
106
|
+
resolvePath: (name, token, fromFile) => {
|
|
110
107
|
// ローカルにファイルが存在するならそれを使う。そうでなければURLとして解釈する。
|
|
111
108
|
let pathname = name
|
|
112
109
|
// eslint-disable-next-line no-prototype-builtins
|
|
@@ -116,10 +113,13 @@ class WebNakoCompiler extends NakoCompiler {
|
|
|
116
113
|
} catch (e) {
|
|
117
114
|
// 単純にパスに変換できなければ、loccation.hrefを参考にパスを組み立てる
|
|
118
115
|
try {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
116
|
+
let baseDir = dirname(fromFile)
|
|
117
|
+
if (baseDir === '') {
|
|
118
|
+
// https://2/3/4.html
|
|
119
|
+
const a = window.location.href.split('/')
|
|
120
|
+
baseDir = '/' + a.slice(3,a.length - 1).join('/')
|
|
121
|
+
}
|
|
122
|
+
pathname = resolveURL(baseDir, name)
|
|
123
123
|
} catch (e) {
|
|
124
124
|
throw new NakoImportError(`取り込み文の引数でパスが解決できません。https:// か http:// で始まるアドレスを指定してください。\n${e}`, token.file, token.line)
|
|
125
125
|
}
|
|
@@ -127,11 +127,11 @@ class WebNakoCompiler extends NakoCompiler {
|
|
|
127
127
|
}
|
|
128
128
|
// .js および .mjs なら JSプラグイン
|
|
129
129
|
if (pathname.endsWith('.js') || pathname.endsWith('.js.txt') || pathname.endsWith('.mjs') || pathname.endsWith('.mjs.txt')) {
|
|
130
|
-
return { filePath:
|
|
130
|
+
return { filePath: pathname, type: 'js' }
|
|
131
131
|
}
|
|
132
132
|
// .nako3 なら なでしこ3プラグイン
|
|
133
133
|
if (pathname.endsWith('.nako3') || pathname.endsWith('.nako3.txt')) {
|
|
134
|
-
return { filePath:
|
|
134
|
+
return { filePath: pathname, type: 'nako3' }
|
|
135
135
|
}
|
|
136
136
|
// ファイル拡張子が未指定の場合
|
|
137
137
|
throw new NakoImportError(`ファイル『${name}』は拡張子が(.nako3|.js|.js.txt|.mjs|.mjs.txt)以外なので取り込めません。`, token.file, token.line)
|
|
@@ -166,6 +166,29 @@ class WebNakoCompiler extends NakoCompiler {
|
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
function dirname(s) {
|
|
170
|
+
const a = s.split('/')
|
|
171
|
+
if (a && a.length > 1) {
|
|
172
|
+
return a.slice(0, a.length - 1).join('/')
|
|
173
|
+
}
|
|
174
|
+
return ''
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function resolveURL(base, s) {
|
|
178
|
+
const baseA = base.split('/')
|
|
179
|
+
const sA = s.split('/')
|
|
180
|
+
for (let p of sA) {
|
|
181
|
+
if (p === '') {continue}
|
|
182
|
+
if (p === '.') {continue}
|
|
183
|
+
if (p === '..') {
|
|
184
|
+
baseA.pop()
|
|
185
|
+
continue
|
|
186
|
+
}
|
|
187
|
+
baseA.push(p)
|
|
188
|
+
}
|
|
189
|
+
return baseA.join('/')
|
|
190
|
+
}
|
|
191
|
+
|
|
169
192
|
// ブラウザなら navigator.nako3 になでしこを登録
|
|
170
193
|
if (typeof (navigator) === 'object' && !navigator.exportWNako3) {
|
|
171
194
|
const nako3 = navigator.nako3 = new WebNakoCompiler()
|
package/tools/nako3edit/run.mjs
CHANGED
|
@@ -9,7 +9,7 @@ const __filename = url.fileURLToPath(import.meta.url);
|
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
10
|
|
|
11
11
|
const nakoHome = path.resolve(path.join(__dirname, '../../'))
|
|
12
|
-
const cnako3 = path.resolve(path.join(nakoHome, 'src/cnako3.
|
|
12
|
+
const cnako3 = path.resolve(path.join(nakoHome, 'src/cnako3.mjs'))
|
|
13
13
|
const nako3edit = path.resolve(path.join(__dirname, 'index.nako3'))
|
|
14
14
|
|
|
15
15
|
let proc = spawn('node', [cnako3, nako3edit])
|