Adding the examples and helper add functionality for JS as well as hiding button to convert outside of development environment.
This commit is contained in:
parent
15b275c0f9
commit
67dd1fd9c3
|
@ -24,6 +24,7 @@
|
||||||
import { addHBSBinding, addJSBinding } from "./utils"
|
import { addHBSBinding, addJSBinding } from "./utils"
|
||||||
import CodeMirrorEditor from "components/common/CodeMirrorEditor.svelte"
|
import CodeMirrorEditor from "components/common/CodeMirrorEditor.svelte"
|
||||||
import { convertToJS } from "@budibase/string-templates"
|
import { convertToJS } from "@budibase/string-templates"
|
||||||
|
import { admin } from "stores/portal"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
@ -62,16 +63,24 @@
|
||||||
|
|
||||||
const updateValue = val => {
|
const updateValue = val => {
|
||||||
valid = isValid(readableToRuntimeBinding(bindings, val))
|
valid = isValid(readableToRuntimeBinding(bindings, val))
|
||||||
console.log(readableToRuntimeBinding(bindings, val))
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
dispatch("change", val)
|
dispatch("change", val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a HBS helper to the expression
|
// Adds a JS/HBS helper to the expression
|
||||||
const addHelper = helper => {
|
const addHelper = (helper, js) => {
|
||||||
hbsValue = addHBSBinding(hbsValue, getCaretPosition(), helper.text)
|
let value
|
||||||
updateValue(hbsValue)
|
const pos = getCaretPosition()
|
||||||
|
if (js) {
|
||||||
|
const decoded = decodeJSBinding(jsValue)
|
||||||
|
value = jsValue = encodeJSBinding(
|
||||||
|
addJSBinding(decoded, pos, helper.text, { helper: true })
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
value = hbsValue = addHBSBinding(hbsValue, pos, helper.text)
|
||||||
|
}
|
||||||
|
updateValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a data binding to the expression
|
// Adds a data binding to the expression
|
||||||
|
@ -108,7 +117,6 @@
|
||||||
|
|
||||||
const convert = () => {
|
const convert = () => {
|
||||||
const runtime = readableToRuntimeBinding(bindings, hbsValue)
|
const runtime = readableToRuntimeBinding(bindings, hbsValue)
|
||||||
console.log(runtime)
|
|
||||||
const runtimeJs = encodeJSBinding(convertToJS(runtime))
|
const runtimeJs = encodeJSBinding(convertToJS(runtime))
|
||||||
jsValue = runtimeToReadableBinding(bindings, runtimeJs)
|
jsValue = runtimeToReadableBinding(bindings, runtimeJs)
|
||||||
hbsValue = null
|
hbsValue = null
|
||||||
|
@ -116,6 +124,17 @@
|
||||||
addBinding("", { forceJS: true })
|
addBinding("", { forceJS: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getHelperExample = (helper, js) => {
|
||||||
|
let example = helper.example || ""
|
||||||
|
if (js) {
|
||||||
|
example = convertToJS(example).split("\n")[0].split("= ")[1]
|
||||||
|
if (example === "null;") {
|
||||||
|
example = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return example || ""
|
||||||
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
valid = isValid(readableToRuntimeBinding(bindings, value))
|
valid = isValid(readableToRuntimeBinding(bindings, value))
|
||||||
})
|
})
|
||||||
|
@ -151,18 +170,21 @@
|
||||||
</section>
|
</section>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
{#if filteredHelpers?.length && !usingJS}
|
{#if filteredHelpers?.length}
|
||||||
<section>
|
<section>
|
||||||
<div class="heading">Helpers</div>
|
<div class="heading">Helpers</div>
|
||||||
<ul>
|
<ul>
|
||||||
{#each filteredHelpers as helper}
|
{#each filteredHelpers as helper}
|
||||||
<li on:click={() => addHelper(helper)}>
|
<li on:click={() => addHelper(helper, usingJS)}>
|
||||||
<div class="helper">
|
<div class="helper">
|
||||||
<div class="helper__name">{helper.displayText}</div>
|
<div class="helper__name">{helper.displayText}</div>
|
||||||
<div class="helper__description">
|
<div class="helper__description">
|
||||||
{@html helper.description}
|
{@html helper.description}
|
||||||
</div>
|
</div>
|
||||||
<pre class="helper__example">{helper.example || ""}</pre>
|
<pre class="helper__example">{getHelperExample(
|
||||||
|
helper,
|
||||||
|
usingJS
|
||||||
|
)}</pre>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -188,9 +210,11 @@
|
||||||
for more details.
|
for more details.
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="convert">
|
{#if $admin.isDev}
|
||||||
<Button secondary on:click={convert}>Convert to JS</Button>
|
<div class="convert">
|
||||||
</div>
|
<Button secondary on:click={convert}>Convert to JS</Button>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</Tab>
|
</Tab>
|
||||||
{#if allowJS}
|
{#if allowJS}
|
||||||
|
|
|
@ -18,10 +18,14 @@ export function addHBSBinding(value, caretPos, binding) {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addJSBinding(value, caretPos, binding) {
|
export function addJSBinding(value, caretPos, binding, { helper } = {}) {
|
||||||
binding = typeof binding === "string" ? binding : binding.path
|
binding = typeof binding === "string" ? binding : binding.path
|
||||||
value = value == null ? "" : value
|
value = value == null ? "" : value
|
||||||
binding = `$("${binding}")`
|
if (!helper) {
|
||||||
|
binding = `$("${binding}")`
|
||||||
|
} else {
|
||||||
|
binding = `helper.${binding}()`
|
||||||
|
}
|
||||||
if (caretPos.start) {
|
if (caretPos.start) {
|
||||||
value =
|
value =
|
||||||
value.substring(0, caretPos.start) +
|
value.substring(0, caretPos.start) +
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
"b"
|
"b"
|
||||||
],
|
],
|
||||||
"numArgs": 2,
|
"numArgs": 2,
|
||||||
"example": "{{ product 10 5 }} -> 50",
|
"example": "{{ multiply 10 5 }} -> 50",
|
||||||
"description": "<p>Return the product of <code>a</code> times <code>b</code>.</p>\n"
|
"description": "<p>Return the product of <code>a</code> times <code>b</code>.</p>\n"
|
||||||
},
|
},
|
||||||
"plus": {
|
"plus": {
|
||||||
|
|
|
@ -108,6 +108,10 @@ function getCommentInfo(file, func) {
|
||||||
if (examples.length > 0) {
|
if (examples.length > 0) {
|
||||||
docs.example = examples.join(" ")
|
docs.example = examples.join(" ")
|
||||||
}
|
}
|
||||||
|
// hacky example fix
|
||||||
|
if (docs.example && docs.example.includes("product")) {
|
||||||
|
docs.example = docs.example.replace("product", "multiply")
|
||||||
|
}
|
||||||
docs.description = blocks[0].trim()
|
docs.description = blocks[0].trim()
|
||||||
return docs
|
return docs
|
||||||
}
|
}
|
||||||
|
@ -166,7 +170,7 @@ function run() {
|
||||||
// convert all markdown to HTML
|
// convert all markdown to HTML
|
||||||
for (let collection of Object.values(outputJSON)) {
|
for (let collection of Object.values(outputJSON)) {
|
||||||
for (let helper of Object.values(collection)) {
|
for (let helper of Object.values(collection)) {
|
||||||
helper.description = marked(helper.description)
|
helper.description = marked.parse(helper.description)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fs.writeFileSync(FILENAME, JSON.stringify(outputJSON, null, 2))
|
fs.writeFileSync(FILENAME, JSON.stringify(outputJSON, null, 2))
|
||||||
|
|
|
@ -22,7 +22,29 @@ function getLayers(fullBlock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVariable(variableName) {
|
function getVariable(variableName) {
|
||||||
return isNaN(parseFloat(variableName)) ? `$("${variableName}")` : variableName
|
if (!variableName || typeof variableName !== "string") {
|
||||||
|
return variableName
|
||||||
|
}
|
||||||
|
// it is an array
|
||||||
|
const arrayOrObject = [",", "{", ":"]
|
||||||
|
let contains = false
|
||||||
|
arrayOrObject.forEach(char => {
|
||||||
|
if (variableName.includes(char)) {
|
||||||
|
contains = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (variableName.startsWith("[") && contains) {
|
||||||
|
return variableName
|
||||||
|
}
|
||||||
|
// it is just a number
|
||||||
|
if (!isNaN(parseFloat(variableName))) {
|
||||||
|
return variableName
|
||||||
|
}
|
||||||
|
if (variableName.startsWith("'") || variableName.startsWith('"')) {
|
||||||
|
return variableName
|
||||||
|
}
|
||||||
|
// extract variable
|
||||||
|
return `$("${variableName}")`
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildList(parts, value) {
|
function buildList(parts, value) {
|
||||||
|
@ -41,17 +63,34 @@ function buildList(parts, value) {
|
||||||
function splitBySpace(layer) {
|
function splitBySpace(layer) {
|
||||||
const parts = []
|
const parts = []
|
||||||
let started = null,
|
let started = null,
|
||||||
|
endChar = null,
|
||||||
last = 0
|
last = 0
|
||||||
|
function add(str) {
|
||||||
|
const startsWith = ["]"]
|
||||||
|
while (startsWith.indexOf(str.substring(0, 1)) !== -1) {
|
||||||
|
str = str.substring(1, str.length)
|
||||||
|
}
|
||||||
|
if (str.length > 0) {
|
||||||
|
parts.push(str.trim())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const continuationChars = ["[", "'", '"']
|
||||||
for (let index = 0; index < layer.length; index++) {
|
for (let index = 0; index < layer.length; index++) {
|
||||||
const char = layer[index]
|
const char = layer[index]
|
||||||
if (char === "[" && started == null) {
|
if (continuationChars.indexOf(char) !== -1 && started == null) {
|
||||||
started = index
|
started = index
|
||||||
} else if (char === "]" && started != null && layer[index + 1] !== ".") {
|
endChar = char === "[" ? "]" : char
|
||||||
parts.push(layer.substring(started, index + 1).trim())
|
} else if (
|
||||||
|
char === endChar &&
|
||||||
|
started != null &&
|
||||||
|
layer[index + 1] !== "."
|
||||||
|
) {
|
||||||
|
add(layer.substring(started, index + 1))
|
||||||
started = null
|
started = null
|
||||||
last = index
|
endChar = null
|
||||||
} else if (started == null && char === " " && last !== index - 1) {
|
last = index + 1
|
||||||
parts.push(layer.substring(last, index).trim())
|
} else if (started == null && char === " ") {
|
||||||
|
add(layer.substring(last, index))
|
||||||
last = index
|
last = index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +98,7 @@ function splitBySpace(layer) {
|
||||||
(!layer.startsWith("[") || parts.length === 0) &&
|
(!layer.startsWith("[") || parts.length === 0) &&
|
||||||
last !== layer.length - 1
|
last !== layer.length - 1
|
||||||
) {
|
) {
|
||||||
parts.push(layer.substring(last, layer.length).trim())
|
add(layer.substring(last, layer.length))
|
||||||
}
|
}
|
||||||
return parts
|
return parts
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,11 +41,43 @@ describe("Test that the string processing works correctly", () => {
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("Should handle many square brackets in helpers", () => {
|
it("should handle many square brackets in helpers", () => {
|
||||||
const response = convertToJS("Hello {{ avg [user].[_id] [user].[_rev] }}")
|
const response = convertToJS("Hello {{ avg [user].[_id] [user].[_rev] }}")
|
||||||
checkLines(response, [
|
checkLines(response, [
|
||||||
"const var1 = helpers.avg($(\"[user].[_id]\"), $(\"[user].[_rev]\"));",
|
"const var1 = helpers.avg($(\"[user].[_id]\"), $(\"[user].[_rev]\"));",
|
||||||
"return `Hello ${var1}`;"
|
"return `Hello ${var1}`;",
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should handle one of the examples (after)", () => {
|
||||||
|
const response = convertToJS("{{ after [1, 2, 3] 1}}")
|
||||||
|
checkLines(response, [
|
||||||
|
"const var1 = helpers.after([1, 2, 3], 1);",
|
||||||
|
"return `${var1}`;",
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should handle one of the examples (equalsLength)", () => {
|
||||||
|
const response = convertToJS("{{equalsLength '[1,2,3]' 3}}")
|
||||||
|
checkLines(response, [
|
||||||
|
"const var1 = helpers.equalsLength('[1,2,3]', 3);",
|
||||||
|
"return `${var1}`;"
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should handle one of the examples (pluck)", () => {
|
||||||
|
const response = convertToJS("{{pluck [{ 'name': 'Bob' }] 'name' }}")
|
||||||
|
checkLines(response, [
|
||||||
|
"const var1 = helpers.pluck([{ 'name': 'Bob' }], 'name');",
|
||||||
|
"return `${var1}`;",
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should handle sorting an array", () => {
|
||||||
|
const response = convertToJS("{{ sort ['b', 'a', 'c'] }}")
|
||||||
|
checkLines(response, [
|
||||||
|
"const var1 = helpers.sort(['b', 'a', 'c']);",
|
||||||
|
"return `${var1}`;",
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue