@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
package/syntax/blocks.js
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
import { extensions, aliasExtensions } from "./extensions.js"
|
|
2
|
+
|
|
3
|
+
// List of classes we're allowed to override.
|
|
4
|
+
|
|
5
|
+
const overrideCategories = [
|
|
6
|
+
"motion",
|
|
7
|
+
"looks",
|
|
8
|
+
"sound",
|
|
9
|
+
"variables",
|
|
10
|
+
"list",
|
|
11
|
+
"events",
|
|
12
|
+
"control",
|
|
13
|
+
"sensing",
|
|
14
|
+
"operators",
|
|
15
|
+
"custom",
|
|
16
|
+
"custom-arg",
|
|
17
|
+
"extension",
|
|
18
|
+
"grey",
|
|
19
|
+
"obsolete",
|
|
20
|
+
...Object.keys(extensions),
|
|
21
|
+
...Object.keys(aliasExtensions),
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
const overrideShapes = [
|
|
25
|
+
"hat",
|
|
26
|
+
"cap",
|
|
27
|
+
"stack",
|
|
28
|
+
"boolean",
|
|
29
|
+
"reporter",
|
|
30
|
+
"object",
|
|
31
|
+
"array",
|
|
32
|
+
"ring",
|
|
33
|
+
"cat",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
// languages that should be displayed right to left
|
|
37
|
+
export const rtlLanguages = ["ar", "ckb", "fa", "he"]
|
|
38
|
+
|
|
39
|
+
// List of commands taken from Scratch
|
|
40
|
+
import scratchCommands from "./commands.js"
|
|
41
|
+
|
|
42
|
+
const inputNumberPat = /%([0-9]+)/
|
|
43
|
+
export const inputPat = /(%[a-zA-Z0-9](?:\.[a-zA-Z0-9]+)?)/
|
|
44
|
+
const inputPatGlobal = new RegExp(inputPat.source, "g")
|
|
45
|
+
export const iconPat = /(@[a-zA-Z]+)/
|
|
46
|
+
const splitPat = new RegExp(`${inputPat.source}|${iconPat.source}| +`, "g")
|
|
47
|
+
|
|
48
|
+
export const hexColorPat = /^#(?:[0-9a-fA-F]{3}){1,2}?$/
|
|
49
|
+
|
|
50
|
+
export function parseInputNumber(part) {
|
|
51
|
+
const m = inputNumberPat.exec(part)
|
|
52
|
+
return m ? +m[1] : 0
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// used for procDefs
|
|
56
|
+
export function parseSpec(spec) {
|
|
57
|
+
const parts = spec.split(splitPat).filter(x => x)
|
|
58
|
+
const inputs = parts.filter(p => inputPat.test(p))
|
|
59
|
+
return {
|
|
60
|
+
spec: spec,
|
|
61
|
+
parts: parts,
|
|
62
|
+
inputs: inputs,
|
|
63
|
+
hash: hashSpec(spec),
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function hashSpec(spec) {
|
|
68
|
+
return minifyHash(spec.replace(inputPatGlobal, " _ "))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function minifyHash(hash) {
|
|
72
|
+
return hash
|
|
73
|
+
.replace(/_/g, " _ ")
|
|
74
|
+
.replace(/ +/g, " ")
|
|
75
|
+
.replace(/[,%?:]/g, "")
|
|
76
|
+
.replace(/ß/g, "ss")
|
|
77
|
+
.replace(/ä/g, "a")
|
|
78
|
+
.replace(/ö/g, "o")
|
|
79
|
+
.replace(/ü/g, "u")
|
|
80
|
+
.replace(". . .", "...")
|
|
81
|
+
.replace(/^…$/, "...")
|
|
82
|
+
.trim()
|
|
83
|
+
.toLowerCase()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const blocksById = {}
|
|
87
|
+
const allBlocks = scratchCommands.map(def => {
|
|
88
|
+
if (!def.id) {
|
|
89
|
+
if (!def.selector) {
|
|
90
|
+
throw new Error(`Missing ID: ${def.spec}`)
|
|
91
|
+
}
|
|
92
|
+
def.id = `sb2:${def.selector}`
|
|
93
|
+
}
|
|
94
|
+
if (!def.spec) {
|
|
95
|
+
throw new Error(`Missing spec: ${def.id}`)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const info = {
|
|
99
|
+
id: def.id, // Used for Scratch 3 translations
|
|
100
|
+
spec: def.spec, // Used for legacy translations.
|
|
101
|
+
parts: def.spec.split(splitPat).filter(x => x),
|
|
102
|
+
selector: def.selector || `sb3:${def.id}`, // Used for JSON marshalling
|
|
103
|
+
inputs: def.inputs == null ? [] : def.inputs,
|
|
104
|
+
shape: def.shape,
|
|
105
|
+
category: def.category,
|
|
106
|
+
hasLoopArrow: !!def.hasLoopArrow,
|
|
107
|
+
}
|
|
108
|
+
if (blocksById[info.id]) {
|
|
109
|
+
throw new Error(`Duplicate ID: ${info.id}`)
|
|
110
|
+
}
|
|
111
|
+
blocksById[info.id] = info
|
|
112
|
+
return info
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
export const unicodeIcons = {
|
|
116
|
+
"@greenFlag": "⚑",
|
|
117
|
+
"@turnRight": "↻",
|
|
118
|
+
"@turnLeft": "↺",
|
|
119
|
+
"@addInput": "▸",
|
|
120
|
+
"@delInput": "◂",
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export const allLanguages = {}
|
|
124
|
+
function loadLanguage(code, language) {
|
|
125
|
+
const blocksByHash = (language.blocksByHash = {})
|
|
126
|
+
|
|
127
|
+
Object.keys(language.commands).forEach(blockId => {
|
|
128
|
+
const nativeSpec = language.commands[blockId]
|
|
129
|
+
const block = blocksById[blockId]
|
|
130
|
+
|
|
131
|
+
const nativeHash = hashSpec(nativeSpec)
|
|
132
|
+
if (!blocksByHash[nativeHash]) {
|
|
133
|
+
blocksByHash[nativeHash] = []
|
|
134
|
+
}
|
|
135
|
+
blocksByHash[nativeHash].push(block)
|
|
136
|
+
|
|
137
|
+
// fallback image replacement, for languages without aliases
|
|
138
|
+
const m = iconPat.exec(block.spec)
|
|
139
|
+
if (m) {
|
|
140
|
+
const image = m[0]
|
|
141
|
+
const hash = nativeHash.replace(hashSpec(image), unicodeIcons[image])
|
|
142
|
+
if (!blocksByHash[hash]) {
|
|
143
|
+
blocksByHash[hash] = []
|
|
144
|
+
}
|
|
145
|
+
blocksByHash[hash].push(block)
|
|
146
|
+
}
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
language.nativeAliases = {}
|
|
150
|
+
Object.keys(language.aliases).forEach(alias => {
|
|
151
|
+
const blockId = language.aliases[alias]
|
|
152
|
+
const block = blocksById[blockId]
|
|
153
|
+
if (block === undefined) {
|
|
154
|
+
throw new Error(`Invalid alias '${blockId}'`)
|
|
155
|
+
}
|
|
156
|
+
const aliasHash = hashSpec(alias)
|
|
157
|
+
if (!blocksByHash[aliasHash]) {
|
|
158
|
+
blocksByHash[aliasHash] = []
|
|
159
|
+
}
|
|
160
|
+
blocksByHash[aliasHash].push(block)
|
|
161
|
+
|
|
162
|
+
if (!language.nativeAliases[blockId]) {
|
|
163
|
+
language.nativeAliases[blockId] = []
|
|
164
|
+
}
|
|
165
|
+
language.nativeAliases[blockId].push(alias)
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
// Some English blocks have legacy names. Wire them
|
|
169
|
+
// into language.blocksByHash
|
|
170
|
+
Object.keys(language.renamedBlocks || {}).forEach(alt => {
|
|
171
|
+
const id = language.renamedBlocks[alt]
|
|
172
|
+
if (!blocksById[id]) {
|
|
173
|
+
throw new Error(`Unknown ID: ${id}`)
|
|
174
|
+
}
|
|
175
|
+
const block = blocksById[id]
|
|
176
|
+
const hash = hashSpec(alt)
|
|
177
|
+
if (!english.blocksByHash[hash]) {
|
|
178
|
+
english.blocksByHash[hash] = []
|
|
179
|
+
}
|
|
180
|
+
english.blocksByHash[hash].push(block)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
language.nativeDropdowns = {}
|
|
184
|
+
Object.keys(language.dropdowns).forEach(name => {
|
|
185
|
+
const nativeName = language.dropdowns[name]
|
|
186
|
+
language.nativeDropdowns[nativeName] = name
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
language.code = code
|
|
190
|
+
allLanguages[code] = language
|
|
191
|
+
}
|
|
192
|
+
export function loadLanguages(languages) {
|
|
193
|
+
Object.keys(languages).forEach(code => loadLanguage(code, languages[code]))
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export const english = {
|
|
197
|
+
aliases: {
|
|
198
|
+
"turn ccw %1 degrees": "MOTION_TURNLEFT",
|
|
199
|
+
"turn left %1 degrees": "MOTION_TURNLEFT",
|
|
200
|
+
"turn cw %1 degrees": "MOTION_TURNRIGHT",
|
|
201
|
+
"turn right %1 degrees": "MOTION_TURNRIGHT",
|
|
202
|
+
"when flag clicked": "EVENT_WHENFLAGCLICKED",
|
|
203
|
+
"when gf clicked": "EVENT_WHENFLAGCLICKED",
|
|
204
|
+
"when green flag clicked": "EVENT_WHENFLAGCLICKED",
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
renamedBlocks: {
|
|
208
|
+
"say %1 for %2 secs": "LOOKS_SAYFORSECS",
|
|
209
|
+
"think %1 for %2 secs": "LOOKS_THINKFORSECS",
|
|
210
|
+
"play sound %1": "SOUND_PLAY",
|
|
211
|
+
"wait %1 secs": "CONTROL_WAIT",
|
|
212
|
+
clear: "pen.clear",
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
definePrefix: ["define"],
|
|
216
|
+
defineSuffix: [],
|
|
217
|
+
|
|
218
|
+
// For ignoring the lt sign in the "when distance < _" block
|
|
219
|
+
ignorelt: ["when distance"],
|
|
220
|
+
|
|
221
|
+
// Valid arguments to "of" dropdown, for resolving ambiguous situations
|
|
222
|
+
math: [
|
|
223
|
+
"abs",
|
|
224
|
+
"floor",
|
|
225
|
+
"ceiling",
|
|
226
|
+
"sqrt",
|
|
227
|
+
"sin",
|
|
228
|
+
"cos",
|
|
229
|
+
"tan",
|
|
230
|
+
"asin",
|
|
231
|
+
"acos",
|
|
232
|
+
"atan",
|
|
233
|
+
"ln",
|
|
234
|
+
"log",
|
|
235
|
+
"e ^",
|
|
236
|
+
"10 ^",
|
|
237
|
+
],
|
|
238
|
+
|
|
239
|
+
// Language name is needed for the English locale as well
|
|
240
|
+
name: "English",
|
|
241
|
+
|
|
242
|
+
// Valid arguments to "sound effect" dropdown, for resolving ambiguous situations
|
|
243
|
+
soundEffects: ["pitch", "pan left/right"],
|
|
244
|
+
|
|
245
|
+
// Valid arguments to "microbit when" dropdown
|
|
246
|
+
microbitWhen: ["moved", "shaken", "jumped"],
|
|
247
|
+
|
|
248
|
+
// For detecting the "stop" cap / stack block
|
|
249
|
+
osis: ["other scripts in sprite", "other scripts in stage"],
|
|
250
|
+
|
|
251
|
+
dropdowns: {},
|
|
252
|
+
|
|
253
|
+
commands: {},
|
|
254
|
+
}
|
|
255
|
+
allBlocks.forEach(info => {
|
|
256
|
+
english.commands[info.id] = info.spec
|
|
257
|
+
})
|
|
258
|
+
loadLanguages({
|
|
259
|
+
en: english,
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
/*****************************************************************************/
|
|
263
|
+
|
|
264
|
+
function registerCheck(id, func) {
|
|
265
|
+
if (!blocksById[id]) {
|
|
266
|
+
throw new Error(`Unknown ID: ${id}`)
|
|
267
|
+
}
|
|
268
|
+
blocksById[id].accepts = func
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function specialCase(id, func) {
|
|
272
|
+
if (!blocksById[id]) {
|
|
273
|
+
throw new Error(`Unknown ID: ${id}`)
|
|
274
|
+
}
|
|
275
|
+
blocksById[id].specialCase = func
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function disambig(id1, id2, test) {
|
|
279
|
+
registerCheck(id1, (_, children, lang) => {
|
|
280
|
+
return test(children, lang)
|
|
281
|
+
})
|
|
282
|
+
registerCheck(id2, (_, children, lang) => {
|
|
283
|
+
return !test(children, lang)
|
|
284
|
+
})
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
disambig("OPERATORS_MATHOP", "SENSING_OF", (children, lang) => {
|
|
288
|
+
// Operators if math function, otherwise sensing "attribute of" block
|
|
289
|
+
const first = children[0]
|
|
290
|
+
if (!first.isInput) {
|
|
291
|
+
return
|
|
292
|
+
}
|
|
293
|
+
const name = first.value
|
|
294
|
+
return lang.math.includes(name)
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
disambig("SOUND_CHANGEEFFECTBY", "LOOKS_CHANGEEFFECTBY", (children, lang) => {
|
|
298
|
+
// Sound if sound effect, otherwise default to graphic effect
|
|
299
|
+
for (const child of children) {
|
|
300
|
+
if (child.shape === "dropdown") {
|
|
301
|
+
const name = child.value
|
|
302
|
+
for (const effect of lang.soundEffects) {
|
|
303
|
+
if (minifyHash(effect) === minifyHash(name)) {
|
|
304
|
+
return true
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return false
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
disambig("SOUND_SETEFFECTO", "LOOKS_SETEFFECTTO", (children, lang) => {
|
|
313
|
+
// Sound if sound effect, otherwise default to graphic effect
|
|
314
|
+
for (const child of children) {
|
|
315
|
+
if (child.shape === "dropdown") {
|
|
316
|
+
const name = child.value
|
|
317
|
+
for (const effect of lang.soundEffects) {
|
|
318
|
+
if (minifyHash(effect) === minifyHash(name)) {
|
|
319
|
+
return true
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return false
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
disambig("DATA_LENGTHOFLIST", "OPERATORS_LENGTH", (children, _lang) => {
|
|
328
|
+
// List block if dropdown, otherwise operators
|
|
329
|
+
const last = children[children.length - 1]
|
|
330
|
+
if (!last.isInput) {
|
|
331
|
+
return
|
|
332
|
+
}
|
|
333
|
+
return last.shape === "dropdown"
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
disambig("DATA_LISTCONTAINSITEM", "OPERATORS_CONTAINS", (children, _lang) => {
|
|
337
|
+
// List block if dropdown, otherwise operators
|
|
338
|
+
const first = children[0]
|
|
339
|
+
if (!first.isInput) {
|
|
340
|
+
return
|
|
341
|
+
}
|
|
342
|
+
return first.shape === "dropdown"
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
disambig("pen.setColor", "pen.setHue", (children, _lang) => {
|
|
346
|
+
// Color block if color input, otherwise numeric
|
|
347
|
+
const last = children[children.length - 1]
|
|
348
|
+
// If variable, assume color input, since the RGBA hack is common.
|
|
349
|
+
// TODO fix Scratch :P
|
|
350
|
+
return (last.isInput && last.isColor) || last.isBlock
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
disambig("microbit.whenGesture", "gdxfor.whenGesture", (children, lang) => {
|
|
354
|
+
for (const child of children) {
|
|
355
|
+
if (child.shape === "dropdown") {
|
|
356
|
+
const name = child.value
|
|
357
|
+
// Yes, "when shaken" gdxfor block exists. But microbit is more common.
|
|
358
|
+
for (const effect of lang.microbitWhen) {
|
|
359
|
+
if (minifyHash(effect) === minifyHash(name)) {
|
|
360
|
+
return true
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return false
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
// This block does not need disambiguation in English;
|
|
369
|
+
// however, many other languages do require that.
|
|
370
|
+
disambig("ev3.buttonPressed", "microbit.isButtonPressed", (children, _lang) => {
|
|
371
|
+
for (const child of children) {
|
|
372
|
+
if (child.shape === "dropdown") {
|
|
373
|
+
// EV3 "button pressed" block uses numeric identifier
|
|
374
|
+
// and does not support "any".
|
|
375
|
+
switch (minifyHash(child.value)) {
|
|
376
|
+
case "1":
|
|
377
|
+
case "2":
|
|
378
|
+
case "3":
|
|
379
|
+
case "4":
|
|
380
|
+
return true
|
|
381
|
+
default:
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return false
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
specialCase("CONTROL_STOP", (_, children, lang) => {
|
|
389
|
+
// Cap block unless argument is "other scripts in sprite"
|
|
390
|
+
const last = children[children.length - 1]
|
|
391
|
+
if (!last.isInput) {
|
|
392
|
+
return
|
|
393
|
+
}
|
|
394
|
+
const value = last.value
|
|
395
|
+
if (lang.osis.includes(value)) {
|
|
396
|
+
return { ...blocksById.CONTROL_STOP, shape: "stack" }
|
|
397
|
+
}
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
export function lookupHash(hash, info, children, languages) {
|
|
401
|
+
for (const lang of languages) {
|
|
402
|
+
if (Object.prototype.hasOwnProperty.call(lang.blocksByHash, hash)) {
|
|
403
|
+
const collisions = lang.blocksByHash[hash]
|
|
404
|
+
for (let block of collisions) {
|
|
405
|
+
if (
|
|
406
|
+
info.shape === "reporter" &&
|
|
407
|
+
block.shape !== "reporter" &&
|
|
408
|
+
block.shape !== "ring"
|
|
409
|
+
) {
|
|
410
|
+
continue
|
|
411
|
+
}
|
|
412
|
+
if (info.shape === "boolean" && block.shape !== "boolean") {
|
|
413
|
+
continue
|
|
414
|
+
}
|
|
415
|
+
if (collisions.length > 1) {
|
|
416
|
+
// Only check in case of collision;
|
|
417
|
+
// perform "disambiguation"
|
|
418
|
+
if (block.accepts && !block.accepts(info, children, lang)) {
|
|
419
|
+
continue
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (block.specialCase) {
|
|
423
|
+
block = block.specialCase(info, children, lang) || block
|
|
424
|
+
}
|
|
425
|
+
return { type: block, lang: lang }
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export function lookupDropdown(name, languages) {
|
|
432
|
+
for (const lang of languages) {
|
|
433
|
+
if (Object.prototype.hasOwnProperty.call(lang.nativeDropdowns, name)) {
|
|
434
|
+
return lang.nativeDropdowns[name]
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export function applyOverrides(info, overrides) {
|
|
440
|
+
for (const name of overrides) {
|
|
441
|
+
if (hexColorPat.test(name)) {
|
|
442
|
+
info.color = name
|
|
443
|
+
info.category = ""
|
|
444
|
+
info.categoryIsDefault = false
|
|
445
|
+
} else if (overrideCategories.includes(name)) {
|
|
446
|
+
info.category = name
|
|
447
|
+
info.categoryIsDefault = false
|
|
448
|
+
} else if (overrideShapes.includes(name)) {
|
|
449
|
+
info.shape = name
|
|
450
|
+
} else if (name === "loop") {
|
|
451
|
+
info.hasLoopArrow = true
|
|
452
|
+
} else if (name === "+" || name === "-") {
|
|
453
|
+
info.diff = name
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
export function blockName(block) {
|
|
459
|
+
const words = []
|
|
460
|
+
for (const child of block.children) {
|
|
461
|
+
if (!child.isLabel) {
|
|
462
|
+
return
|
|
463
|
+
}
|
|
464
|
+
words.push(child.value)
|
|
465
|
+
}
|
|
466
|
+
return words.join(" ")
|
|
467
|
+
}
|