sandbox page, multiple sidebars, select field docs
This commit is contained in:
parent
6d4cb1f96a
commit
dd6d8d9c3b
9 changed files with 136 additions and 76 deletions
|
|
@ -20,17 +20,13 @@ export default {
|
|||
|
||||
fields: {
|
||||
OPERATION: {
|
||||
description: `
|
||||
Round: rounds up if .5 or higher, down otherwise
|
||||
Floor: rounds down
|
||||
Ceiling: rounds up
|
||||
`,
|
||||
bytecodeProperty: "operation",
|
||||
description: "Select which rounding operation to perform on the input:",
|
||||
options: [
|
||||
["Round", "round"],
|
||||
["Floor", "floor"],
|
||||
["Ceiling", "ceiling"],
|
||||
]
|
||||
["Round", "round", "if .5 or higher: round up; otherwise round down"],
|
||||
["Floor", "floor", "rounds down"],
|
||||
["Ceiling", "ceiling", "rounds up"],
|
||||
],
|
||||
bytecodeProperty: "operation",
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -39,15 +39,42 @@ export default defineConfig({
|
|||
},
|
||||
|
||||
nav: [
|
||||
{ text: '', link: '/sandbox' },
|
||||
{ text: 'Home', link: '/' },
|
||||
{ text: 'Getting Started', link: '/getting-started' },
|
||||
{ text: 'The Blocks', link: '/block-index' },
|
||||
{ text: 'Examples', link: '/automation-examples' }
|
||||
],
|
||||
|
||||
sidebar: [
|
||||
blocksSidebar
|
||||
],
|
||||
sidebar: {
|
||||
// covers /blocks/* and /block-index
|
||||
"/block": [ blocksSidebar ],
|
||||
|
||||
// devtools for the sandbox
|
||||
"/sandbox": [
|
||||
{
|
||||
"text": "Tools",
|
||||
"items": [
|
||||
{
|
||||
"text": "Custom Feed Names",
|
||||
"link": "#"
|
||||
},
|
||||
{
|
||||
"text": "Weather Locations",
|
||||
"link": "#"
|
||||
},
|
||||
{
|
||||
"text": "IO Bytecode Explorer",
|
||||
"link": "#"
|
||||
},
|
||||
{
|
||||
"text": "Blockly JSON Explorer",
|
||||
"link": "#"
|
||||
},
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: REPO }
|
||||
|
|
|
|||
|
|
@ -1,33 +1,42 @@
|
|||
<script setup>
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
import { dispose, inject } from "../blockly/blockly_app.js"
|
||||
import initialWorkspace from "../blockly/workspace.json"
|
||||
|
||||
const
|
||||
props = defineProps(['block'])
|
||||
{ block, width="100%", height="200px", toolbox=true } = defineProps(
|
||||
['block', 'width', 'height', 'toolbox']
|
||||
),
|
||||
injectOptions = {},
|
||||
options = {
|
||||
injectOptions,
|
||||
workspaceJson: block
|
||||
? {
|
||||
"blocks": {
|
||||
"languageVersion": 0,
|
||||
"blocks": [
|
||||
{
|
||||
"type": block,
|
||||
"deletable": false,
|
||||
"x": 50,
|
||||
"y": 50
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
: initialWorkspace
|
||||
}
|
||||
|
||||
if(!toolbox) {
|
||||
injectOptions.toolbox = false
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
console.log('mounted, block:', props.block)
|
||||
inject("blocklyDiv", {
|
||||
injectOptions: { toolbox: false },
|
||||
workspaceJson: {
|
||||
"blocks": {
|
||||
"languageVersion": 0,
|
||||
"blocks": [
|
||||
{
|
||||
"type": props.block,
|
||||
"deletable": false,
|
||||
"x": 50,
|
||||
"y": 50
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
inject("blocklyDiv", options)
|
||||
})
|
||||
|
||||
// clear workspace
|
||||
onUnmounted(() => {
|
||||
console.log('unmounted')
|
||||
// clear workspace
|
||||
dispose()
|
||||
})
|
||||
</script>
|
||||
|
|
@ -38,8 +47,10 @@
|
|||
|
||||
<style>
|
||||
div#blocklyDiv {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
/* width: 100%; */
|
||||
width: v-bind(width);
|
||||
/* height: 200px; */
|
||||
height: v-bind(height);
|
||||
|
||||
.injectionDiv {
|
||||
border-radius: 5px;
|
||||
|
|
|
|||
9
docs/sandbox.md
Normal file
9
docs/sandbox.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
title: Blockly Sandbox
|
||||
# layout: page
|
||||
aside: false
|
||||
---
|
||||
|
||||
# Time to Play!
|
||||
|
||||
<BlocklyWorkspace height="800px" />
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { capitalize, find, forEach, map } from 'lodash-es'
|
||||
|
||||
import { cleanDir, copyDir, write, totalBytesWritten } from "./export_util.js"
|
||||
import { cleanDir, write, totalBytesWritten } from "./export_util.js"
|
||||
import DefinitionSet from '#src/definition_set.js'
|
||||
import toBlockMarkdown from "#src/docs/render_block.js"
|
||||
|
||||
|
|
@ -11,24 +11,25 @@ const startTime = Date.now()
|
|||
console.log("\nStarting Documentation Export")
|
||||
console.log("=======================")
|
||||
|
||||
const definitionSet = await DefinitionSet.load()
|
||||
|
||||
cleanDir("docs/blockly")
|
||||
// TODO: instead, export exactly what we need
|
||||
copyDir("export", "docs/blockly")
|
||||
definitionSet.export({ to: "docs/blockly" })
|
||||
|
||||
cleanDir("docs/blocks")
|
||||
|
||||
const definitionSet = await DefinitionSet.load()
|
||||
const categories = definitionSet.getCategories()
|
||||
const
|
||||
categories = definitionSet.getCategories(),
|
||||
|
||||
// INIT SIDEBAR
|
||||
const blockSidebar = {
|
||||
text: 'Blocks',
|
||||
items: map(categories, ({ name }) => ({
|
||||
text: name,
|
||||
collapsed: true,
|
||||
items: []
|
||||
}))
|
||||
}
|
||||
// INIT SIDEBAR
|
||||
blockSidebar = {
|
||||
text: 'Blocks',
|
||||
items: map(categories, ({ name }) => ({
|
||||
text: name,
|
||||
collapsed: true,
|
||||
items: []
|
||||
}))
|
||||
}
|
||||
|
||||
forEach(definitionSet.blocks, blockDefinition => {
|
||||
// skip disabled blocks
|
||||
|
|
@ -36,9 +37,10 @@ forEach(definitionSet.blocks, blockDefinition => {
|
|||
|
||||
// mirror the blocks/**/*.js path structure
|
||||
const docPath = blockDefinition.definitionPath.replace(/.js$/, '.md')
|
||||
write(`docs/blocks/${docPath}`, toBlockMarkdown(blockDefinition)) // EXPORT MARKDOWN
|
||||
// DEDICATED DOC PAGE FOR BLOCK
|
||||
write(`docs/blocks/${docPath}`, toBlockMarkdown(blockDefinition))
|
||||
|
||||
// APPEND TO SIDEBAR
|
||||
// BLOCK SIDEBAR ITEM
|
||||
const
|
||||
blockSidebarPath = `/blocks/${docPath.slice(0, -3)}`,
|
||||
sidebarEntry = {
|
||||
|
|
@ -55,6 +57,7 @@ forEach(definitionSet.blocks, blockDefinition => {
|
|||
throw new Error(`Block category (${ category.name }) not present in sidebar!`)
|
||||
}
|
||||
|
||||
// ADD TO SIDEBAR
|
||||
sidebarCategory.items.push(sidebarEntry)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,25 +1,9 @@
|
|||
import { capitalize, filter, invokeMap, map } from 'lodash-es'
|
||||
import { capitalize, filter, invokeMap } from 'lodash-es'
|
||||
|
||||
import { toBlockJSON } from '#src/importer/block_processor/index.js'
|
||||
import { niceTemplate } from '#src/util.js'
|
||||
|
||||
|
||||
const niceTemplate = tplString => {
|
||||
const
|
||||
lines = tplString.split("\n"),
|
||||
firstLineBlank = /^\s*$/.test(lines[0]),
|
||||
remainingLines = lines.slice(1, -1),
|
||||
indentCounts = map(remainingLines, line => line.search(/\S/)),
|
||||
firstLineLeastIndented = indentCounts[0] >= Math.min(...indentCounts.slice(1, -1))
|
||||
|
||||
// ensure first line is blank and every other line has at least as much whitespace as the first line
|
||||
if(firstLineBlank && firstLineLeastIndented) {
|
||||
// drop the first line, remove X whitespace chars from the rest and join with newline
|
||||
return map(remainingLines, line => line.slice(indentCounts[0])).join("\n")
|
||||
}
|
||||
|
||||
return tplString
|
||||
}
|
||||
|
||||
class BlockDefinition {
|
||||
definitionSet = null
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ const
|
|||
},
|
||||
|
||||
renderWorkspace = definition => {
|
||||
return `<BlocklyWorkspace block="${ definition.type }" />`
|
||||
return `<BlocklyWorkspace :toolbox="false" block="${ definition.type }" />`
|
||||
},
|
||||
|
||||
renderOutput = definition => {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
import { capitalize, filter, isArray, isObject, isString, map } from 'lodash-es'
|
||||
import { capitalize, filter, isArray, isObject, isString, map, mapValues, values } from 'lodash-es'
|
||||
|
||||
import { niceTemplate } from '#src/util.js'
|
||||
|
||||
|
||||
const
|
||||
getLineObjects = definition => filter(map(filter(definition.lines, isArray), "[1]"), isObject),
|
||||
|
||||
renderFields = definition => {
|
||||
const fields = filter(getLineObjects(definition), "field")
|
||||
const fields = filter(getLineObjects(definition), "field").concat(
|
||||
values(mapValues(definition.fields, (newField, name) => {
|
||||
newField.field = name
|
||||
return newField
|
||||
}))
|
||||
)
|
||||
|
||||
if(!fields.length) { return "This block has no form fields." }
|
||||
|
||||
|
|
@ -16,9 +23,10 @@ const
|
|||
const lines = []
|
||||
|
||||
// title for this field
|
||||
lines.push(`### Field: \`${capitalize(field.field)}\``)
|
||||
lines.push(`### \`${capitalize(field.field)}\`:`)
|
||||
|
||||
// add lines based on what properties are present
|
||||
Object.hasOwn(field, 'description') && lines.push(niceTemplate(field.description).replaceAll("\n", "\n\n"))
|
||||
Object.hasOwn(field, 'text') && lines.push(renderTextField(field))
|
||||
Object.hasOwn(field, 'checked') && lines.push(renderCheckboxField(field))
|
||||
Object.hasOwn(field, 'options') && lines.push(renderSelectField(field))
|
||||
|
|
@ -32,10 +40,12 @@ const
|
|||
|
||||
renderSelectField = selectField => {
|
||||
const
|
||||
optionLabels = map(selectField.options, 0),
|
||||
optionList = map(optionLabels, label => ` - ${label}`).join("\n")
|
||||
optionList = map(selectField.options, ([ label, , doc ]) => doc
|
||||
? `- \`${label}\`: ${doc}`
|
||||
: `- \`${label}\``
|
||||
).join("\n")
|
||||
|
||||
return `- Options:\n${optionList}`
|
||||
return optionList
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
20
src/util.js
Normal file
20
src/util.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { map } from 'lodash-es'
|
||||
|
||||
|
||||
export const
|
||||
niceTemplate = tplString => {
|
||||
const
|
||||
lines = tplString.split("\n"),
|
||||
firstLineBlank = /^\s*$/.test(lines[0]),
|
||||
remainingLines = lines.slice(1, -1),
|
||||
indentCounts = map(remainingLines, line => line.search(/\S/)),
|
||||
firstLineLeastIndented = indentCounts[0] >= Math.min(...indentCounts.slice(1, -1))
|
||||
|
||||
// ensure first line is blank and every other line has at least as much whitespace as the first line
|
||||
if(firstLineBlank && firstLineLeastIndented) {
|
||||
// drop the first line, remove X whitespace chars from the rest and join with newline
|
||||
return map(remainingLines, line => line.slice(indentCounts[0])).join("\n")
|
||||
}
|
||||
|
||||
return tplString
|
||||
}
|
||||
Loading…
Reference in a new issue