Add name validation to snippets
This commit is contained in:
parent
7dc67185ed
commit
01679fbd01
|
@ -17,6 +17,7 @@
|
||||||
export const hide = () => drawer.hide()
|
export const hide = () => drawer.hide()
|
||||||
|
|
||||||
const roughValidNameRegex = /^[_$A-Z\xA0-\uFFFF][_$A-Z0-9\xA0-\uFFFF]*$/i
|
const roughValidNameRegex = /^[_$A-Z\xA0-\uFFFF][_$A-Z0-9\xA0-\uFFFF]*$/i
|
||||||
|
const firstCharNumberRegex = /^[0-9].*$/
|
||||||
|
|
||||||
let drawer
|
let drawer
|
||||||
let name = ""
|
let name = ""
|
||||||
|
@ -26,7 +27,7 @@
|
||||||
$: name = snippet?.name || "MySnippet"
|
$: name = snippet?.name || "MySnippet"
|
||||||
$: code = snippet?.code ? encodeJSBinding(snippet.code) : ""
|
$: code = snippet?.code ? encodeJSBinding(snippet.code) : ""
|
||||||
$: rawJS = decodeJSBinding(code)
|
$: rawJS = decodeJSBinding(code)
|
||||||
$: nameValid = validateName(name)
|
$: nameError = validateName(name)
|
||||||
|
|
||||||
const saveSnippet = async () => {
|
const saveSnippet = async () => {
|
||||||
await snippetStore.saveSnippet({
|
await snippetStore.saveSnippet({
|
||||||
|
@ -48,14 +49,20 @@
|
||||||
// try executing it and see if it's valid JS. The initial regex prevents
|
// try executing it and see if it's valid JS. The initial regex prevents
|
||||||
// against any potential XSS attacks here.
|
// against any potential XSS attacks here.
|
||||||
const validateName = name => {
|
const validateName = name => {
|
||||||
|
if (!name?.length) {
|
||||||
|
return "Name is required"
|
||||||
|
}
|
||||||
|
if (firstCharNumberRegex.test(name)) {
|
||||||
|
return "Can't start with a number"
|
||||||
|
}
|
||||||
if (!roughValidNameRegex.test(name)) {
|
if (!roughValidNameRegex.test(name)) {
|
||||||
return false
|
return "No special characters or spaces"
|
||||||
}
|
}
|
||||||
const js = `(function ${name}(){return true})()`
|
const js = `(function ${name}(){return true})()`
|
||||||
try {
|
try {
|
||||||
return eval(js) === true
|
return eval(js) === true ? null : "Invalid name"
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false
|
return "Invalid name"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -65,14 +72,11 @@
|
||||||
{#if snippet}
|
{#if snippet}
|
||||||
{snippet.name}
|
{snippet.name}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="name" class:invalid={!nameValid}>
|
<div class="name" class:invalid={nameError != null}>
|
||||||
<span>Name</span>
|
<span>Name</span>
|
||||||
<Input bind:value={name} />
|
<Input bind:value={name} />
|
||||||
{#if !nameValid}
|
{#if nameError}
|
||||||
<AbsTooltip
|
<AbsTooltip text={nameError} type={TooltipType.Negative}>
|
||||||
text="Alphanumeric characters only, with no spaces"
|
|
||||||
type={TooltipType.Negative}
|
|
||||||
>
|
|
||||||
<Icon
|
<Icon
|
||||||
name="Help"
|
name="Help"
|
||||||
size="S"
|
size="S"
|
||||||
|
@ -87,7 +91,7 @@
|
||||||
{#if snippet}
|
{#if snippet}
|
||||||
<Button warning on:click={deleteSnippet}>Delete</Button>
|
<Button warning on:click={deleteSnippet}>Delete</Button>
|
||||||
{/if}
|
{/if}
|
||||||
<Button cta on:click={saveSnippet} disabled={!rawJS?.length || !nameValid}>
|
<Button cta on:click={saveSnippet} disabled={nameError != null}>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
@ -117,9 +121,12 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.name.invalid :global(input) {
|
.name :global(input) {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
.name.invalid :global(input) {
|
||||||
|
padding-right: 32px;
|
||||||
|
}
|
||||||
.name :global(.icon) {
|
.name :global(.icon) {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
|
|
Loading…
Reference in New Issue