Refactored `escape` utils
This commit is contained in:
parent
f011e3f107
commit
1c3a323387
|
@ -1,6 +1,8 @@
|
||||||
.jsoneditor {
|
.jsoneditor {
|
||||||
border: 1px solid #3883fa;
|
border: 1px solid #3883fa;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jsoneditor-node {
|
.jsoneditor-node {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { h, Component } from 'preact'
|
import { h, Component } from 'preact'
|
||||||
import isObject from './utils/isObject'
|
import isObject from './utils/isObject'
|
||||||
import escapeHTML from './utils/escapeHTML'
|
import { escapeHTML, unescapeHTML } from './utils/escape'
|
||||||
import unescapeHTML from './utils/unescapeHTML'
|
|
||||||
import getInnerText from './utils/getInnerText'
|
import getInnerText from './utils/getInnerText'
|
||||||
import stringConvert from './utils/stringConvert'
|
import stringConvert from './utils/stringConvert'
|
||||||
import valueType, {isUrl} from './utils/valueType'
|
import valueType, {isUrl} from './utils/valueType'
|
||||||
|
@ -83,7 +82,7 @@ export default class JSONNode extends Component {
|
||||||
? this.renderReadonly(index)
|
? this.renderReadonly(index)
|
||||||
: this.renderField(field, parent, this.onChangeField),
|
: this.renderField(field, parent, this.onChangeField),
|
||||||
this.renderSeparator(),
|
this.renderSeparator(),
|
||||||
this.renderValue(value, this.onChangeValue)
|
this.renderValue(value, this.onChangeValue, this.onClickUrl, this.onKeyDownUrl)
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
@ -99,7 +98,7 @@ export default class JSONNode extends Component {
|
||||||
return h('div', {
|
return h('div', {
|
||||||
class: 'jsoneditor-field' + (hasParent ? '' : ' jsoneditor-readonly'),
|
class: 'jsoneditor-field' + (hasParent ? '' : ' jsoneditor-readonly'),
|
||||||
contentEditable: hasParent,
|
contentEditable: hasParent,
|
||||||
spellCheck: "false", // FIXME: turning off spellcheck doesn't work
|
spellCheck: 'false',
|
||||||
onBlur: onChangeField
|
onBlur: onChangeField
|
||||||
}, content)
|
}, content)
|
||||||
}
|
}
|
||||||
|
@ -108,7 +107,7 @@ export default class JSONNode extends Component {
|
||||||
return h('div', {class: 'jsoneditor-separator'}, ':')
|
return h('div', {class: 'jsoneditor-separator'}, ':')
|
||||||
}
|
}
|
||||||
|
|
||||||
renderValue (value, onChangeValue) {
|
renderValue (value, onChangeValue, onClickUrl, onKeyDownUrl) {
|
||||||
const type = valueType (value)
|
const type = valueType (value)
|
||||||
const _isUrl = isUrl(value)
|
const _isUrl = isUrl(value)
|
||||||
const valueClass = 'jsoneditor-value jsoneditor-' + type + (_isUrl ? ' jsoneditor-url' : '')
|
const valueClass = 'jsoneditor-value jsoneditor-' + type + (_isUrl ? ' jsoneditor-url' : '')
|
||||||
|
@ -116,10 +115,10 @@ export default class JSONNode extends Component {
|
||||||
return h('div', {
|
return h('div', {
|
||||||
class: valueClass,
|
class: valueClass,
|
||||||
contentEditable: true,
|
contentEditable: true,
|
||||||
spellCheck: "false", // FIXME: turning off spellcheck doesn't work
|
spellCheck: 'false', // FIXME: turning off spellcheck doesn't work
|
||||||
onInput: onChangeValue,
|
onInput: onChangeValue,
|
||||||
onClick: _isUrl ? this.onClickUrl : null,
|
onClick: _isUrl ? onClickUrl : null,
|
||||||
onKeyDown: _isUrl ? this.onKeyDownUrl: null,
|
onKeyDown: _isUrl ? onKeyDownUrl: null,
|
||||||
title: _isUrl ? 'Ctrl+Click or ctrl+Enter to open url' : null
|
title: _isUrl ? 'Ctrl+Click or ctrl+Enter to open url' : null
|
||||||
}, escapeHTML(value))
|
}, escapeHTML(value))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
import parseJSON from './parseJSON'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* escape a text, such that it can be displayed safely in an HTML element
|
||||||
|
* @param {String} text
|
||||||
|
* @param {boolean} [escapeUnicode=false]
|
||||||
|
* @return {String} escapedText
|
||||||
|
*/
|
||||||
|
export function escapeHTML (text, escapeUnicode = false) {
|
||||||
|
if (typeof text !== 'string') {
|
||||||
|
return String(text)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var htmlEscaped = String(text)
|
||||||
|
.replace(/ /g, ' \u00a0') // replace double space with an nbsp and space
|
||||||
|
.replace(/^ /, '\u00a0') // space at start
|
||||||
|
.replace(/ $/, '\u00a0') // space at end
|
||||||
|
|
||||||
|
var json = JSON.stringify(htmlEscaped)
|
||||||
|
var html = json.substring(1, json.length - 1)
|
||||||
|
if (escapeUnicode === true) {
|
||||||
|
html = escapeUnicodeChars(html)
|
||||||
|
}
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape unicode characters.
|
||||||
|
* For example input '\u2661' (length 1) will output '\\u2661' (length 5).
|
||||||
|
* @param {string} text
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
function escapeUnicodeChars (text) {
|
||||||
|
// see https://www.wikiwand.com/en/UTF-16
|
||||||
|
// note: we leave surrogate pairs as two individual chars,
|
||||||
|
// as JSON doesn't interpret them as a single unicode char.
|
||||||
|
return text.replace(/[\u007F-\uFFFF]/g, function(c) {
|
||||||
|
return '\\u'+('0000' + c.charCodeAt(0).toString(16)).slice(-4)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* unescape a string.
|
||||||
|
* @param {String} escapedText
|
||||||
|
* @return {String} text
|
||||||
|
*/
|
||||||
|
export function unescapeHTML (escapedText) {
|
||||||
|
var json = '"' + escapeJSON(escapedText) + '"'
|
||||||
|
var htmlEscaped = parseJSON(json)
|
||||||
|
|
||||||
|
return htmlEscaped.replace(/\u00A0/g, ' ') // nbsp character
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* escape a text to make it a valid JSON string. The method will:
|
||||||
|
* - replace unescaped double quotes with '\"'
|
||||||
|
* - replace unescaped backslash with '\\'
|
||||||
|
* - replace returns with '\n'
|
||||||
|
* @param {String} text
|
||||||
|
* @return {String} escapedText
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
export function escapeJSON (text) {
|
||||||
|
// TODO: replace with some smart regex (only when a new solution is faster!)
|
||||||
|
var escaped = ''
|
||||||
|
var i = 0
|
||||||
|
while (i < text.length) {
|
||||||
|
var c = text.charAt(i)
|
||||||
|
if (c == '\n') {
|
||||||
|
escaped += '\\n'
|
||||||
|
}
|
||||||
|
else if (c == '\\') {
|
||||||
|
escaped += c
|
||||||
|
i++
|
||||||
|
|
||||||
|
c = text.charAt(i)
|
||||||
|
if (c === '' || '"\\/bfnrtu'.indexOf(c) == -1) {
|
||||||
|
escaped += '\\' // no valid escape character
|
||||||
|
}
|
||||||
|
escaped += c
|
||||||
|
}
|
||||||
|
else if (c == '"') {
|
||||||
|
escaped += '\\"'
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
escaped += c
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
return escaped
|
||||||
|
}
|
|
@ -1,43 +0,0 @@
|
||||||
/**
|
|
||||||
* escape a text, such that it can be displayed safely in an HTML element
|
|
||||||
* @param {String} text
|
|
||||||
* @param {boolean} [escapeUnicode=false]
|
|
||||||
* @return {String} escapedText
|
|
||||||
*/
|
|
||||||
export default function escapeHTML (text, escapeUnicode = false) {
|
|
||||||
if (typeof text !== 'string') {
|
|
||||||
return String(text)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var htmlEscaped = String(text)
|
|
||||||
// TODO: cleanup redundant character replacements
|
|
||||||
// .replace(/&/g, '&') // must be replaced first!
|
|
||||||
// .replace(/</g, '<')
|
|
||||||
// .replace(/>/g, '>')
|
|
||||||
.replace(/ /g, ' \u00a0') // replace double space with an nbsp and space
|
|
||||||
.replace(/^ /, '\u00a0') // space at start
|
|
||||||
.replace(/ $/, '\u00a0') // space at end
|
|
||||||
|
|
||||||
var json = JSON.stringify(htmlEscaped)
|
|
||||||
var html = json.substring(1, json.length - 1)
|
|
||||||
if (escapeUnicode === true) {
|
|
||||||
html = escapeUnicodeChars(html)
|
|
||||||
}
|
|
||||||
return html
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Escape unicode characters.
|
|
||||||
* For example input '\u2661' (length 1) will output '\\u2661' (length 5).
|
|
||||||
* @param {string} text
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
function escapeUnicodeChars (text) {
|
|
||||||
// see https://www.wikiwand.com/en/UTF-16
|
|
||||||
// note: we leave surrogate pairs as two individual chars,
|
|
||||||
// as JSON doesn't interpret them as a single unicode char.
|
|
||||||
return text.replace(/[\u007F-\uFFFF]/g, function(c) {
|
|
||||||
return '\\u'+('0000' + c.charCodeAt(0).toString(16)).slice(-4)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
import parseJSON from './parseJSON'
|
|
||||||
/**
|
|
||||||
* unescape a string.
|
|
||||||
* @param {String} escapedText
|
|
||||||
* @return {String} text
|
|
||||||
*/
|
|
||||||
export default function unescapeHTML (escapedText) {
|
|
||||||
var json = '"' + escapeJSON(escapedText) + '"'
|
|
||||||
var htmlEscaped = parseJSON(json)
|
|
||||||
|
|
||||||
return htmlEscaped
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>')
|
|
||||||
.replace(/ |\u00A0/g, ' ')
|
|
||||||
.replace(/&/g, '&') // must be replaced last
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* escape a text to make it a valid JSON string. The method will:
|
|
||||||
* - replace unescaped double quotes with '\"'
|
|
||||||
* - replace unescaped backslash with '\\'
|
|
||||||
* - replace returns with '\n'
|
|
||||||
* @param {String} text
|
|
||||||
* @return {String} escapedText
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
export function escapeJSON (text) {
|
|
||||||
// TODO: replace with some smart regex (only when a new solution is faster!)
|
|
||||||
var escaped = ''
|
|
||||||
var i = 0
|
|
||||||
while (i < text.length) {
|
|
||||||
var c = text.charAt(i)
|
|
||||||
if (c == '\n') {
|
|
||||||
escaped += '\\n'
|
|
||||||
}
|
|
||||||
else if (c == '\\') {
|
|
||||||
escaped += c
|
|
||||||
i++
|
|
||||||
|
|
||||||
c = text.charAt(i)
|
|
||||||
if (c === '' || '"\\/bfnrtu'.indexOf(c) == -1) {
|
|
||||||
escaped += '\\' // no valid escape character
|
|
||||||
}
|
|
||||||
escaped += c
|
|
||||||
}
|
|
||||||
else if (c == '"') {
|
|
||||||
escaped += '\\"'
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
escaped += c
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
return escaped
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var util = require('../src/js/util');
|
var util = require('./js/util');
|
||||||
|
|
||||||
// console.log('TEST', util.parsePath('.items[3].name'));
|
// console.log('TEST', util.parsePath('.items[3].name'));
|
||||||
// console.log('TEST', util.parsePath('.items[*].name'));
|
// console.log('TEST', util.parsePath('.items[*].name'));
|
||||||
|
|
Loading…
Reference in New Issue