Move selection highlighting in builder preview in to client library and replace handlebars with mustache again

This commit is contained in:
Andrew Kingston 2020-12-02 13:49:24 +00:00
parent 0a72b0e21b
commit 859ae5f8a4
8 changed files with 49 additions and 59 deletions

View File

@ -22,15 +22,6 @@ export default `<html>
// 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
window["##BUDIBASE_PREVIEW_PAGE##"] = page

View File

@ -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"
},

View File

@ -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 => {

View File

@ -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 = {
"<": "&lt;",
">": "&gt;",
}
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)
}
/**

View File

@ -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()

View File

@ -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"

View File

@ -1,11 +1,14 @@
<script>
import { getContext } from "svelte"
const { DataProvider } = getContext("sdk")
const { DataProvider, styleable } = getContext("sdk")
const component = getContext("component")
export let table
</script>
<div use:styleable={$component.styles}>
<DataProvider row={{ tableId: table }}>
<slot />
</DataProvider>
</div>

View File

@ -1,7 +1,10 @@
<script>
import { onMount, getContext } from "svelte"
const { API, screenStore, routeStore, DataProvider } = getContext("sdk")
const { API, screenStore, routeStore, DataProvider, styleable } = getContext(
"sdk"
)
const component = getContext("component")
export let table
@ -35,7 +38,9 @@
</script>
{#if row}
<div use:styleable={$component.styles}>
<DataProvider {row}>
<slot />
</DataProvider>
</div>
{/if}