From 859ae5f8a4771465addd3cd5b356497f4bbb8038 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 2 Dec 2020 13:49:24 +0000 Subject: [PATCH] Move selection highlighting in builder preview in to client library and replace handlebars with mustache again --- .../AppPreview/iframeTemplate.js | 9 ----- packages/client/package.json | 2 +- .../client/src/components/Component.svelte | 5 +-- .../client/src/utils/enrichDataBinding.js | 20 +++++++++- packages/client/src/utils/styleable.js | 11 ++++-- packages/client/yarn.lock | 37 +++---------------- .../standard-components/src/NewRow.svelte | 11 ++++-- .../standard-components/src/RowDetail.svelte | 13 +++++-- 8 files changed, 49 insertions(+), 59 deletions(-) diff --git a/packages/builder/src/components/userInterface/AppPreview/iframeTemplate.js b/packages/builder/src/components/userInterface/AppPreview/iframeTemplate.js index 6c18def11b..3a0cecce9e 100644 --- a/packages/builder/src/components/userInterface/AppPreview/iframeTemplate.js +++ b/packages/builder/src/components/userInterface/AppPreview/iframeTemplate.js @@ -21,15 +21,6 @@ export default ` // Extract data from message const { selectedComponentId, page, screen } = JSON.parse(event.data) - - // Update selected component style - if (selectedComponentStyle) { - document.head.removeChild(selectedComponentStyle) - } - selectedComponentStyle = document.createElement("style"); - document.head.appendChild(selectedComponentStyle) - var selectedCss = '[data-bb-id="' + selectedComponentId + '"]' + '{border:2px solid #0055ff !important;}' - selectedComponentStyle.appendChild(document.createTextNode(selectedCss)) // Set some flags so the app knows we're in the builder window["##BUDIBASE_IN_BUILDER##"] = true diff --git a/packages/client/package.json b/packages/client/package.json index 13914d178c..685f500f59 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "deep-equal": "^2.0.1", - "handlebars": "^4.7.6", + "mustache": "^4.0.1", "regexparam": "^1.3.0", "svelte-spa-router": "^3.0.5" }, diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 90428dbf34..56591133e5 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -20,11 +20,10 @@ $: children = definition._children $: id = definition._id $: enrichedProps = enrichProps(definition, $dataContext, $bindingStore) + $: selected = id === $builderStore.selectedComponentId // Update component context - // ID is duplicated inside style so that the "styleable" helper can set - // an ID data tag for unique reference to components - $: componentStore.set({ id, styles: { ...definition._styles, id } }) + $: componentStore.set({ id, styles: { ...definition._styles, selected } }) // Gets the component constructor for the specified component const getComponentConstructor = component => { diff --git a/packages/client/src/utils/enrichDataBinding.js b/packages/client/src/utils/enrichDataBinding.js index d25dced9db..5de6b31a89 100644 --- a/packages/client/src/utils/enrichDataBinding.js +++ b/packages/client/src/utils/enrichDataBinding.js @@ -1,4 +1,20 @@ -import handlebars from "handlebars" +import mustache from "mustache" + +// this is a much more liberal version of mustache's escape function +// ...just ignoring < and > to prevent tags from user input +// original version here https://github.com/janl/mustache.js/blob/4b7908f5c9fec469a11cfaed2f2bed23c84e1c5c/mustache.js#L78 +const entityMap = { + "<": "<", + ">": ">", +} +mustache.escape = text => { + if (text == null || typeof text !== "string") { + return text + } + return text.replace(/[<>]/g, function fromEntityMap(s) { + return entityMap[s] || s + }) +} // Regex to test inputs with to see if they are likely candidates for mustache const looksLikeMustache = /{{.*}}/ @@ -15,7 +31,7 @@ export const enrichDataBinding = (input, context) => { if (!looksLikeMustache.test(input)) { return input } - return handlebars.render(input, context) + return mustache.render(input, context) } /** diff --git a/packages/client/src/utils/styleable.js b/packages/client/src/utils/styleable.js index 95cb1f18a3..1953139714 100644 --- a/packages/client/src/utils/styleable.js +++ b/packages/client/src/utils/styleable.js @@ -1,8 +1,11 @@ /** * Helper to build a CSS string from a style object */ -const buildStyleString = styles => { +const buildStyleString = (styles, selected) => { let str = "" + if (selected) { + styles.border = "2px solid #0055ff !important" + } Object.entries(styles).forEach(([style, value]) => { if (style && value != null) { str += `${style}: ${value}; ` @@ -20,6 +23,7 @@ export const styleable = (node, styles = {}) => { // Creates event listeners and applies initial styles const setupStyles = newStyles => { + const selected = newStyles.selected const normalStyles = newStyles.normal || {} const hoverStyles = { ...normalStyles, @@ -27,17 +31,16 @@ export const styleable = (node, styles = {}) => { } applyNormalStyles = () => { - node.style = buildStyleString(normalStyles) + node.style = buildStyleString(normalStyles, selected) } applyHoverStyles = () => { - node.style = buildStyleString(hoverStyles) + node.style = buildStyleString(hoverStyles, selected) } // Add listeners to toggle hover styles node.addEventListener("mouseover", applyHoverStyles) node.addEventListener("mouseout", applyNormalStyles) - node.setAttribute("data-bb-id", newStyles.id) // Apply initial normal styles applyNormalStyles() diff --git a/packages/client/yarn.lock b/packages/client/yarn.lock index 32db8aa1d0..e90defb427 100644 --- a/packages/client/yarn.lock +++ b/packages/client/yarn.lock @@ -829,18 +829,6 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -handlebars@^4.7.6: - version "4.7.6" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" - integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA== - dependencies: - minimist "^1.2.5" - neo-async "^2.6.0" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" - har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -1374,15 +1362,10 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -neo-async@^2.6.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== +mustache@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.0.1.tgz#d99beb031701ad433338e7ea65e0489416c854a2" + integrity sha512-yL5VE97+OXn4+Er3THSmTdCFCtx5hHWzrolvH+JObZnUYwuaG7XV+Ch4fR2cIrcYI0tFHxS7iyFYl14bW8y2sA== nwsapi@^2.2.0: version "2.2.0" @@ -1841,7 +1824,7 @@ source-map-support@~0.5.10: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -2011,11 +1994,6 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -uglify-js@^3.1.4: - version "3.12.1" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.1.tgz#78307f539f7b9ca5557babb186ea78ad30cc0375" - integrity sha512-o8lHP20KjIiQe5b/67Rh68xEGRrc2SRsCuuoYclXXoC74AfSRGblU1HKzJWH3HxPZ+Ort85fWHpSX7KwBUC9CQ== - universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -2135,11 +2113,6 @@ word-wrap@~1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" diff --git a/packages/standard-components/src/NewRow.svelte b/packages/standard-components/src/NewRow.svelte index 8b9c57892d..68dcac0b11 100644 --- a/packages/standard-components/src/NewRow.svelte +++ b/packages/standard-components/src/NewRow.svelte @@ -1,11 +1,14 @@ - - - +
+ + + +
diff --git a/packages/standard-components/src/RowDetail.svelte b/packages/standard-components/src/RowDetail.svelte index d260e414d9..7f01341665 100644 --- a/packages/standard-components/src/RowDetail.svelte +++ b/packages/standard-components/src/RowDetail.svelte @@ -1,7 +1,10 @@ {#if row} - - - +
+ + + +
{/if}