@nitro-bolt/scratchblocks 1.1.0
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/LICENSE +18 -0
- package/README.md +205 -0
- package/browser.es.js +8 -0
- package/browser.js +8 -0
- package/build/scratchblocks.min.es.js +11 -0
- package/build/scratchblocks.min.es.js.map +1 -0
- package/build/scratchblocks.min.js +11 -0
- package/build/scratchblocks.min.js.map +1 -0
- package/build/translations-all-es.js +10 -0
- package/build/translations-all.js +10 -0
- package/build/translations-es.js +10 -0
- package/build/translations.js +10 -0
- package/index.js +163 -0
- package/locales/ab.json +261 -0
- package/locales/af.json +261 -0
- package/locales/all.js +161 -0
- package/locales/am.json +262 -0
- package/locales/an.json +261 -0
- package/locales/ar.json +261 -0
- package/locales/ast.json +261 -0
- package/locales/az.json +262 -0
- package/locales/be.json +261 -0
- package/locales/bg.json +261 -0
- package/locales/bn.json +261 -0
- package/locales/ca.json +267 -0
- package/locales/ckb.json +261 -0
- package/locales/cs.json +267 -0
- package/locales/cy.json +266 -0
- package/locales/da.json +261 -0
- package/locales/de.json +266 -0
- package/locales/el.json +268 -0
- package/locales/eo.json +261 -0
- package/locales/es-419.json +261 -0
- package/locales/es.json +266 -0
- package/locales/et.json +261 -0
- package/locales/eu.json +261 -0
- package/locales/fa.json +266 -0
- package/locales/fi.json +261 -0
- package/locales/fil.json +262 -0
- package/locales/forums.js +37 -0
- package/locales/fr.json +266 -0
- package/locales/fy.json +261 -0
- package/locales/ga.json +261 -0
- package/locales/gd.json +266 -0
- package/locales/gl.json +261 -0
- package/locales/ha.json +261 -0
- package/locales/he.json +266 -0
- package/locales/hi.json +266 -0
- package/locales/hr.json +266 -0
- package/locales/ht.json +261 -0
- package/locales/hu.json +267 -0
- package/locales/hy.json +261 -0
- package/locales/id.json +266 -0
- package/locales/is.json +261 -0
- package/locales/it.json +266 -0
- package/locales/ja-Hira.json +268 -0
- package/locales/ja.json +268 -0
- package/locales/ka.json +261 -0
- package/locales/kk.json +263 -0
- package/locales/km.json +261 -0
- package/locales/ko.json +261 -0
- package/locales/ku.json +263 -0
- package/locales/lt.json +261 -0
- package/locales/lv.json +261 -0
- package/locales/mi.json +261 -0
- package/locales/mn.json +262 -0
- package/locales/nb.json +266 -0
- package/locales/nl.json +266 -0
- package/locales/nn.json +261 -0
- package/locales/nso.json +261 -0
- package/locales/oc.json +261 -0
- package/locales/or.json +262 -0
- package/locales/pl.json +266 -0
- package/locales/pt-br.json +261 -0
- package/locales/pt.json +266 -0
- package/locales/qu.json +261 -0
- package/locales/rap.json +263 -0
- package/locales/ro.json +266 -0
- package/locales/ru.json +266 -0
- package/locales/sk.json +261 -0
- package/locales/sl.json +266 -0
- package/locales/sr.json +261 -0
- package/locales/sv.json +261 -0
- package/locales/sw.json +261 -0
- package/locales/th.json +261 -0
- package/locales/tn.json +261 -0
- package/locales/tr.json +269 -0
- package/locales/uk.json +261 -0
- package/locales/uz.json +262 -0
- package/locales/vi.json +262 -0
- package/locales/xh.json +261 -0
- package/locales/zh-cn.json +266 -0
- package/locales/zh-tw.json +266 -0
- package/locales/zu.json +261 -0
- package/package.json +77 -0
- package/scratch3/blocks.js +959 -0
- package/scratch3/draw.js +404 -0
- package/scratch3/index.js +12 -0
- package/scratch3/style.css.js +226 -0
- package/scratch3/style.js +807 -0
- package/syntax/blocks.js +467 -0
- package/syntax/commands.js +1692 -0
- package/syntax/extensions.js +33 -0
- package/syntax/index.js +17 -0
- package/syntax/model.js +427 -0
- package/syntax/syntax.js +941 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
When a new extension is added:
|
|
3
|
+
1) Add it to extensions object
|
|
4
|
+
2) Add its blocks to commands.js
|
|
5
|
+
3) Add icon width/height to scratch3/blocks.js IconView
|
|
6
|
+
4) Add icon to scratch3/style.js
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Moved extension aliases: key is current, value is legacy.
|
|
10
|
+
export const movedExtensions = {
|
|
11
|
+
pen: "pen",
|
|
12
|
+
video: "sensing",
|
|
13
|
+
music: "sound",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const extensions = {
|
|
17
|
+
...movedExtensions,
|
|
18
|
+
tts: "tts",
|
|
19
|
+
translate: "translate",
|
|
20
|
+
microbit: "microbit",
|
|
21
|
+
wedo: "wedo",
|
|
22
|
+
makeymakey: "makeymakey",
|
|
23
|
+
ev3: "ev3",
|
|
24
|
+
boost: "boost",
|
|
25
|
+
gdxfor: "gdxfor",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Extension aliases accepted in addition to movedExtensions.
|
|
29
|
+
// Key is alias, value is real extension name
|
|
30
|
+
export const aliasExtensions = {
|
|
31
|
+
wedo2: "wedo",
|
|
32
|
+
text2speech: "tts",
|
|
33
|
+
}
|
package/syntax/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { parse } from "./syntax.js"
|
|
2
|
+
|
|
3
|
+
export {
|
|
4
|
+
Label,
|
|
5
|
+
Icon,
|
|
6
|
+
Input,
|
|
7
|
+
Newline,
|
|
8
|
+
Block,
|
|
9
|
+
Comment,
|
|
10
|
+
Glow,
|
|
11
|
+
Script,
|
|
12
|
+
Document,
|
|
13
|
+
} from "./model.js"
|
|
14
|
+
|
|
15
|
+
export { allLanguages, loadLanguages } from "./blocks.js"
|
|
16
|
+
|
|
17
|
+
export { extensions, movedExtensions, aliasExtensions } from "./extensions.js"
|
package/syntax/model.js
ADDED
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
function assert(bool, message) {
|
|
2
|
+
if (!bool) {
|
|
3
|
+
throw new Error(`Assertion failed! ${message || ""}`)
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function indent(text) {
|
|
8
|
+
return text
|
|
9
|
+
.split("\n")
|
|
10
|
+
.map(line => {
|
|
11
|
+
return ` ${line}`
|
|
12
|
+
})
|
|
13
|
+
.join("\n")
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
parseSpec,
|
|
18
|
+
inputPat,
|
|
19
|
+
parseInputNumber,
|
|
20
|
+
iconPat,
|
|
21
|
+
rtlLanguages,
|
|
22
|
+
unicodeIcons,
|
|
23
|
+
} from "./blocks.js"
|
|
24
|
+
|
|
25
|
+
export class Label {
|
|
26
|
+
constructor(value, cls) {
|
|
27
|
+
this.value = value
|
|
28
|
+
this.cls = cls || ""
|
|
29
|
+
this.el = null
|
|
30
|
+
this.height = 12
|
|
31
|
+
this.metrics = null
|
|
32
|
+
this.x = 0
|
|
33
|
+
}
|
|
34
|
+
get isLabel() {
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
stringify() {
|
|
39
|
+
if (this.value === "<" || this.value === ">") {
|
|
40
|
+
return this.value
|
|
41
|
+
}
|
|
42
|
+
return this.value.replace(/([<>[\](){}])/g, "\\$1")
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class Icon {
|
|
47
|
+
constructor(name) {
|
|
48
|
+
this.name = name
|
|
49
|
+
this.isArrow = name === "loopArrow"
|
|
50
|
+
|
|
51
|
+
assert(Icon.icons[name], `no info for icon ${name}`)
|
|
52
|
+
}
|
|
53
|
+
get isIcon() {
|
|
54
|
+
return true
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static get icons() {
|
|
58
|
+
return {
|
|
59
|
+
greenFlag: true,
|
|
60
|
+
stopSign: true,
|
|
61
|
+
turnLeft: true,
|
|
62
|
+
turnRight: true,
|
|
63
|
+
loopArrow: true,
|
|
64
|
+
addInput: true,
|
|
65
|
+
delInput: true,
|
|
66
|
+
list: true,
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
stringify() {
|
|
71
|
+
return unicodeIcons[`@${this.name}`] || `@${this.name}`
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export class Input {
|
|
76
|
+
constructor(shape, value, menu) {
|
|
77
|
+
this.shape = shape
|
|
78
|
+
this.value = value
|
|
79
|
+
this.menu = menu || null
|
|
80
|
+
|
|
81
|
+
this.isRound = shape === "number" || shape === "number-dropdown"
|
|
82
|
+
this.isBoolean = shape === "boolean"
|
|
83
|
+
this.isObject = shape === "object"
|
|
84
|
+
this.isArray = shape === "array"
|
|
85
|
+
this.isStack = shape === "stack"
|
|
86
|
+
this.isInset =
|
|
87
|
+
shape === "boolean" ||
|
|
88
|
+
shape === "object" ||
|
|
89
|
+
shape === "array" ||
|
|
90
|
+
shape === "stack" ||
|
|
91
|
+
shape === "reporter"
|
|
92
|
+
this.isColor = shape === "color"
|
|
93
|
+
this.hasArrow = shape === "dropdown" || shape === "number-dropdown"
|
|
94
|
+
this.isDarker =
|
|
95
|
+
shape === "boolean" || shape === "stack" || shape === "dropdown"
|
|
96
|
+
this.isSquare =
|
|
97
|
+
shape === "string" || shape === "color" || shape === "dropdown"
|
|
98
|
+
|
|
99
|
+
this.hasLabel = !(this.isColor || this.isInset)
|
|
100
|
+
this.label = this.hasLabel
|
|
101
|
+
? new Label(value, `literal-${this.shape}`)
|
|
102
|
+
: null
|
|
103
|
+
this.x = 0
|
|
104
|
+
}
|
|
105
|
+
get isInput() {
|
|
106
|
+
return true
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
stringify() {
|
|
110
|
+
if (this.isColor) {
|
|
111
|
+
assert(this.value[0] === "#")
|
|
112
|
+
return `[${this.value}]`
|
|
113
|
+
}
|
|
114
|
+
// Order sensitive; see #439
|
|
115
|
+
let text = (this.value ? String(this.value) : "")
|
|
116
|
+
.replace(/([\]\\])/g, "\\$1")
|
|
117
|
+
.replace(/ v$/, " \\v")
|
|
118
|
+
if (this.hasArrow) {
|
|
119
|
+
text += " v"
|
|
120
|
+
}
|
|
121
|
+
return this.isRound
|
|
122
|
+
? `(${text})`
|
|
123
|
+
: this.isSquare
|
|
124
|
+
? `[${text}]`
|
|
125
|
+
: this.isBoolean
|
|
126
|
+
? "<>"
|
|
127
|
+
: this.isObject
|
|
128
|
+
? "{}"
|
|
129
|
+
: this.isArray
|
|
130
|
+
? "[]"
|
|
131
|
+
: this.isStack
|
|
132
|
+
? "{}"
|
|
133
|
+
: text
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
translate(_lang) {
|
|
137
|
+
if (this.hasArrow) {
|
|
138
|
+
const value = this.menu || this.value
|
|
139
|
+
this.value = value // TODO translate dropdown value
|
|
140
|
+
this.label = new Label(this.value, `literal-${this.shape}`)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export class Newline {
|
|
146
|
+
get isNewline() {
|
|
147
|
+
return true
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
stringify() {
|
|
151
|
+
return "\\n"
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export class Block {
|
|
156
|
+
constructor(info, children, comment) {
|
|
157
|
+
assert(info)
|
|
158
|
+
this.info = { ...info }
|
|
159
|
+
this.children = children
|
|
160
|
+
this.comment = comment || null
|
|
161
|
+
this.diff = null
|
|
162
|
+
|
|
163
|
+
const shape = this.info.shape
|
|
164
|
+
this.isHat = shape === "hat" || shape === "cat" || shape === "define-hat"
|
|
165
|
+
this.hasPuzzle =
|
|
166
|
+
shape === "stack" ||
|
|
167
|
+
shape === "hat" ||
|
|
168
|
+
shape === "cat" ||
|
|
169
|
+
shape === "c-block"
|
|
170
|
+
this.isFinal = /cap/.test(shape)
|
|
171
|
+
this.isCommand = shape === "stack" || shape === "cap" || /block/.test(shape)
|
|
172
|
+
this.isOutline = shape === "outline"
|
|
173
|
+
this.isReporter =
|
|
174
|
+
shape === "reporter" || shape === "object" || shape === "array"
|
|
175
|
+
this.isObject = shape === "object"
|
|
176
|
+
this.isArray = shape === "array"
|
|
177
|
+
this.isBoolean = shape === "boolean"
|
|
178
|
+
|
|
179
|
+
this.isRing = shape === "ring"
|
|
180
|
+
this.hasScript = /block/.test(shape)
|
|
181
|
+
this.isElse = shape === "celse"
|
|
182
|
+
this.isEnd = shape === "cend"
|
|
183
|
+
}
|
|
184
|
+
get isBlock() {
|
|
185
|
+
return true
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
stringify(extras) {
|
|
189
|
+
let firstInput = null
|
|
190
|
+
let checkAlias = false
|
|
191
|
+
const text = this.children
|
|
192
|
+
.map(child => {
|
|
193
|
+
if (child.isIcon) {
|
|
194
|
+
checkAlias = true
|
|
195
|
+
}
|
|
196
|
+
if (!firstInput && !(child.isLabel || child.isIcon)) {
|
|
197
|
+
firstInput = child
|
|
198
|
+
}
|
|
199
|
+
return child.isScript
|
|
200
|
+
? `\n${indent(child.stringify())}\n`
|
|
201
|
+
: child.stringify().trim() + " "
|
|
202
|
+
})
|
|
203
|
+
.join("")
|
|
204
|
+
.trim()
|
|
205
|
+
|
|
206
|
+
const lang = this.info.language
|
|
207
|
+
if (checkAlias && lang && this.info.selector) {
|
|
208
|
+
const aliases = lang.nativeAliases[this.info.id]
|
|
209
|
+
if (aliases && aliases.length) {
|
|
210
|
+
let alias = aliases[0]
|
|
211
|
+
// TODO make translate() not in-place, and use that
|
|
212
|
+
if (inputPat.test(alias) && firstInput) {
|
|
213
|
+
alias = alias.replace(inputPat, firstInput.stringify())
|
|
214
|
+
}
|
|
215
|
+
return alias
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const isNitroShape =
|
|
220
|
+
this.info.shape === "object" || this.info.shape === "array"
|
|
221
|
+
let overrides = extras || ""
|
|
222
|
+
if (
|
|
223
|
+
this.info.categoryIsDefault === false ||
|
|
224
|
+
(this.info.category === "custom-arg" &&
|
|
225
|
+
(this.isReporter || this.isBoolean)) ||
|
|
226
|
+
(this.info.category === "custom" && this.info.shape === "stack")
|
|
227
|
+
) {
|
|
228
|
+
if (overrides) {
|
|
229
|
+
overrides += " "
|
|
230
|
+
}
|
|
231
|
+
overrides += this.info.category
|
|
232
|
+
}
|
|
233
|
+
const overrideText = overrides ? ` :: ${overrides}` : ""
|
|
234
|
+
if (this.hasScript) {
|
|
235
|
+
if (!isNitroShape) {
|
|
236
|
+
return text + overrideText + "\nend"
|
|
237
|
+
}
|
|
238
|
+
const firstNewline = text.indexOf("\n")
|
|
239
|
+
if (firstNewline === -1) {
|
|
240
|
+
return text + overrideText + "\nend"
|
|
241
|
+
}
|
|
242
|
+
return (
|
|
243
|
+
text.slice(0, firstNewline).trimEnd() +
|
|
244
|
+
overrideText +
|
|
245
|
+
text.slice(firstNewline) +
|
|
246
|
+
"\nend"
|
|
247
|
+
)
|
|
248
|
+
}
|
|
249
|
+
if (isNitroShape) {
|
|
250
|
+
return this.isObject
|
|
251
|
+
? `{${text}${overrideText}}`
|
|
252
|
+
: `[${text}${overrideText}]`
|
|
253
|
+
}
|
|
254
|
+
const textWithOverrides = text + overrideText
|
|
255
|
+
return this.info.shape === "reporter"
|
|
256
|
+
? `(${textWithOverrides})`
|
|
257
|
+
: this.info.shape === "boolean"
|
|
258
|
+
? `<${textWithOverrides}>`
|
|
259
|
+
: textWithOverrides
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
translate(lang, isShallow) {
|
|
263
|
+
if (!lang) {
|
|
264
|
+
throw new Error("Missing language")
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const id = this.info.id
|
|
268
|
+
if (!id) {
|
|
269
|
+
return
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (id === "PROCEDURES_DEFINITION") {
|
|
273
|
+
// Find the first 'outline' child (there should be exactly one).
|
|
274
|
+
const outline = this.children.find(child => child.isOutline)
|
|
275
|
+
|
|
276
|
+
this.children = []
|
|
277
|
+
for (const word of lang.definePrefix) {
|
|
278
|
+
this.children.push(new Label(word))
|
|
279
|
+
}
|
|
280
|
+
this.children.push(outline)
|
|
281
|
+
for (const word of lang.defineSuffix) {
|
|
282
|
+
this.children.push(new Label(word))
|
|
283
|
+
}
|
|
284
|
+
return
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const oldSpec = this.info.language.commands[id]
|
|
288
|
+
|
|
289
|
+
const nativeSpec = lang.commands[id]
|
|
290
|
+
if (!nativeSpec) {
|
|
291
|
+
return
|
|
292
|
+
}
|
|
293
|
+
const nativeInfo = parseSpec(nativeSpec)
|
|
294
|
+
|
|
295
|
+
const rawArgs = this.children.filter(
|
|
296
|
+
child => !child.isLabel && !child.isIcon,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
if (!isShallow) {
|
|
300
|
+
rawArgs.forEach(child => child.translate(lang))
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Work out indexes of existing children
|
|
304
|
+
const oldParts = parseSpec(oldSpec).parts
|
|
305
|
+
const oldInputOrder = oldParts
|
|
306
|
+
.map(part => parseInputNumber(part))
|
|
307
|
+
.filter(x => x)
|
|
308
|
+
|
|
309
|
+
let highestNumber = 0
|
|
310
|
+
const args = oldInputOrder.map(number => {
|
|
311
|
+
highestNumber = Math.max(highestNumber, number)
|
|
312
|
+
return rawArgs[number - 1]
|
|
313
|
+
})
|
|
314
|
+
const remainingArgs = rawArgs.slice(highestNumber)
|
|
315
|
+
|
|
316
|
+
// Get new children by index
|
|
317
|
+
this.children = nativeInfo.parts
|
|
318
|
+
.map(part => {
|
|
319
|
+
part = part.trim()
|
|
320
|
+
if (!part) {
|
|
321
|
+
return
|
|
322
|
+
}
|
|
323
|
+
const number = parseInputNumber(part)
|
|
324
|
+
if (number) {
|
|
325
|
+
return args[number - 1]
|
|
326
|
+
}
|
|
327
|
+
return iconPat.test(part) ? new Icon(part.slice(1)) : new Label(part)
|
|
328
|
+
})
|
|
329
|
+
.filter(x => x)
|
|
330
|
+
|
|
331
|
+
// Push any remaining children, so we pick up C block bodies
|
|
332
|
+
remainingArgs.forEach((arg, index) => {
|
|
333
|
+
if (index === 1 && this.info.id === "CONTROL_IF") {
|
|
334
|
+
this.children.push(new Label(lang.commands.CONTROL_ELSE))
|
|
335
|
+
}
|
|
336
|
+
this.children.push(arg)
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
this.info.language = lang
|
|
340
|
+
this.info.isRTL = rtlLanguages.includes(lang.code)
|
|
341
|
+
this.info.categoryIsDefault = true
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export class Comment {
|
|
346
|
+
constructor(value, hasBlock) {
|
|
347
|
+
this.label = new Label(value, "comment-label")
|
|
348
|
+
this.width = null
|
|
349
|
+
this.hasBlock = hasBlock
|
|
350
|
+
}
|
|
351
|
+
get isComment() {
|
|
352
|
+
return true
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
stringify() {
|
|
356
|
+
return `// ${this.label.value}`
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export class Glow {
|
|
361
|
+
constructor(child) {
|
|
362
|
+
assert(child)
|
|
363
|
+
this.child = child
|
|
364
|
+
if (child.isBlock) {
|
|
365
|
+
this.shape = child.info.shape
|
|
366
|
+
this.info = child.info
|
|
367
|
+
} else {
|
|
368
|
+
this.shape = "stack"
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
get isGlow() {
|
|
372
|
+
return true
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
stringify() {
|
|
376
|
+
if (this.child.isBlock) {
|
|
377
|
+
return this.child.stringify("+")
|
|
378
|
+
}
|
|
379
|
+
const lines = this.child.stringify().split("\n")
|
|
380
|
+
return lines.map(line => `+ ${line}`).join("\n")
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
translate(lang) {
|
|
384
|
+
this.child.translate(lang)
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export class Script {
|
|
389
|
+
constructor(blocks) {
|
|
390
|
+
this.blocks = blocks
|
|
391
|
+
this.isEmpty = !blocks.length
|
|
392
|
+
this.isFinal = !this.isEmpty && blocks[blocks.length - 1].isFinal
|
|
393
|
+
}
|
|
394
|
+
get isScript() {
|
|
395
|
+
return true
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
stringify() {
|
|
399
|
+
return this.blocks
|
|
400
|
+
.map(block => {
|
|
401
|
+
let line = block.stringify()
|
|
402
|
+
if (block.comment) {
|
|
403
|
+
line += ` ${block.comment.stringify()}`
|
|
404
|
+
}
|
|
405
|
+
return line
|
|
406
|
+
})
|
|
407
|
+
.join("\n")
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
translate(lang) {
|
|
411
|
+
this.blocks.forEach(block => block.translate(lang))
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export class Document {
|
|
416
|
+
constructor(scripts) {
|
|
417
|
+
this.scripts = scripts
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
stringify() {
|
|
421
|
+
return this.scripts.map(script => script.stringify()).join("\n\n")
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
translate(lang) {
|
|
425
|
+
this.scripts.forEach(script => script.translate(lang))
|
|
426
|
+
}
|
|
427
|
+
}
|