14 |
ScratchScript Playground
15 |
16 | Here is a playground use to debug ScratchScript compiler.
17 | If you like, you can make it as a drynamic code editor.
18 |
19 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/playground/playground.js:
--------------------------------------------------------------------------------
1 | import GUI, { AppStateHOC } from 'scratch-gui'
2 | import ScratchScript from '../index'
3 | import React from 'react'
4 | import ReactDOM from 'react-dom'
5 | import CodeMirror from 'codemirror'
6 | import DefaultProject from './default.sb3'
7 | import Package from '../../package.json'
8 | import JSZip from 'jszip'
9 | import defaultsDeep from 'lodash.defaultsdeep'
10 | const appTarget = document.querySelector('#scratchgui')
11 | const textArea = document.querySelector('textarea')
12 | GUI.setAppElement(appTarget)
13 | const WrappedGui = AppStateHOC(GUI)
14 | const defaultCode = `var direction = 0;
15 | when events.flagClicked() {
16 | looks.sayFor('Hello ScratchScript!', 3);
17 | forever {
18 | direction = 1;
19 | repeat (10) {
20 | motion.changeY(5 * direction);
21 | }
22 | if (direction == 1) {
23 | direction = -1;
24 | } else {
25 | direction = 1;
26 | }
27 | }
28 | }`
29 |
30 | window.CodeArea = CodeMirror.fromTextArea(textArea, {
31 | lineNumbers: true
32 | })
33 | window.CodeArea.setValue(defaultCode)
34 | window.CodeArea.getWrapperElement().style = 'height: calc(100% - 2rem); margin: 1rem; flex: 0.35; border-style: solid; border-width: 1px; border-color: black'
35 |
36 | const compiledTemplate = {
37 | targets: [{
38 | isStage: true,
39 | name: 'Stage',
40 | variables: {},
41 | lists: {},
42 | broadcasts: {},
43 | blocks: {},
44 | comments: {},
45 | currentCostume: 0,
46 | costumes: [],
47 | sounds: [],
48 | volume: 100,
49 | layerOrder: 0,
50 | tempo: 60,
51 | videoTransparency: 50,
52 | videoState: 'off',
53 | textToSpeechLanguage: null
54 | }],
55 | monitors: [],
56 | extensions: [],
57 | meta: {
58 | semver: '3.0.0',
59 | agent: 'ScratchScriptKit/' + Package.version
60 | }
61 | }
62 |
63 | // Register change and send to vm
64 | function onVmInit (vm) {
65 | let loadingProject = false
66 | let delayHandle = null
67 | let requiredUpdate = false
68 | async function compile (code) {
69 | if (loadingProject) return
70 | loadingProject = true
71 | try {
72 | const t = Date.now()
73 | const rawCode = code.getValue()
74 | console.log(rawCode)
75 | const ast = ScratchScript.parser(rawCode)
76 | console.log(Date.now() - t, ast)
77 | const result = await ScratchScript.generator({ ast })
78 | console.log(Date.now() - t, result)
79 | const newProj = defaultsDeep({}, compiledTemplate)
80 | const stage = newProj.targets[0]
81 | stage.blocks = result.blocks
82 | for (const variable of result.ast.variables) {
83 | if (!variable.value) {
84 | stage.variables[variable.id] = [variable.name, '']
85 | } else if (variable.value.value instanceof Array) {
86 | stage.lists[variable.id] = [variable.name, variable.value ? variable.value.value.map(v => v.value) : []]
87 | } else {
88 | stage.variables[variable.id] = [variable.name, variable.value ? variable.value.value : '']
89 | }
90 | }
91 | console.log(newProj)
92 | const zip = await JSZip.loadAsync(DefaultProject)
93 | zip.file('project.json',
94 | JSON.stringify(
95 | defaultsDeep(
96 | {},
97 | JSON.parse(
98 | await zip.file('project.json')
99 | .async('text')
100 | ), newProj
101 | )
102 | )
103 | )
104 | await vm.loadProject(await zip.generateAsync({ type: 'uint8array' }))
105 | loadingProject = false
106 | } catch (err) {
107 | console.warn(err)
108 | }
109 | if (requiredUpdate) {
110 | requiredUpdate = false
111 | compile(code)
112 | return
113 | }
114 | loadingProject = false
115 | }
116 | window.CodeArea.on('change', code => {
117 | requiredUpdate = true
118 | if (delayHandle) clearTimeout(delayHandle)
119 | delayHandle = setTimeout(() => {
120 | requiredUpdate = false
121 | compile(code)
122 | }, 1000)
123 | })
124 | loadingProject = true
125 | vm.loadProject(DefaultProject).then(() => { loadingProject = false })
126 | console.log('Registered VM!', vm)
127 | }
128 |
129 | window.GUI = ReactDOM.render(React.createElement(WrappedGui, {
130 | canSave: false,
131 | isStandalone: true,
132 | backpackVisible: false,
133 | onVmInit
134 | }), appTarget)
135 |
--------------------------------------------------------------------------------
/src/project/emptyAudio.js:
--------------------------------------------------------------------------------
1 | // A empty audio in mp3 format.
2 |
3 | export default {
4 | hash: '94b8c2c5d15e5a3d77c2e34eed3c7c87',
5 | filename: '94b8c2c5d15e5a3d77c2e34eed3c7c87.mp3',
6 | type: 'mp3',
7 | data: new Uint8Array([
8 | 73, 68, 51, 4, 0, 0, 0, 0, 1, 6, 84, 88,
9 | 88, 88, 0, 0, 0, 18, 0, 0, 3, 109, 97, 106,
10 | 111, 114, 95, 98, 114, 97, 110, 100, 0, 105,
11 | 115, 111, 109, 0, 84, 88, 88, 88, 0, 0, 0, 19,
12 | 0, 0, 3, 109, 105, 110, 111, 114, 95, 118,
13 | 101, 114, 115, 105, 111, 110, 0, 53, 49, 50,
14 | 0, 84, 88, 88, 88, 0, 0, 0, 32, 0, 0, 3, 99,
15 | 111, 109, 112, 97, 116, 105, 98, 108, 101,
16 | 95, 98, 114, 97, 110, 100, 115, 0, 105, 115,
17 | 111, 109, 105, 115, 111, 50, 109, 112, 52,
18 | 49, 0, 84, 83, 83, 69, 0, 0, 0, 15, 0, 0, 3,
19 | 76, 97, 118, 102, 53, 56, 46, 51, 49, 46,
20 | 49, 48, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21 | 255, 251, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23 | 0, 0, 0, 0, 0, 0, 0, 0, 73, 110, 102, 111, 0,
24 | 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, 0,
25 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
26 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
27 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
28 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31 | 0, 0, 0, 0, 0, 76, 97, 118, 99, 53, 56, 46, 53,
32 | 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33 | 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, 215, 127, 0, 0,
34 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
35 | ])
36 | }
37 |
--------------------------------------------------------------------------------
/src/project/emptySvg.js:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | data: '