Refactored `escape` utils
This commit is contained in:
parent
f011e3f107
commit
1c3a323387
|
@ -1,6 +1,8 @@
|
|||
.jsoneditor {
|
||||
border: 1px solid #3883fa;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
.jsoneditor-node {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { h, Component } from 'preact'
|
||||
import isObject from './utils/isObject'
|
||||
import escapeHTML from './utils/escapeHTML'
|
||||
import unescapeHTML from './utils/unescapeHTML'
|
||||
import { escapeHTML, unescapeHTML } from './utils/escape'
|
||||
import getInnerText from './utils/getInnerText'
|
||||
import stringConvert from './utils/stringConvert'
|
||||
import valueType, {isUrl} from './utils/valueType'
|
||||
|
@ -83,7 +82,7 @@ export default class JSONNode extends Component {
|
|||
? this.renderReadonly(index)
|
||||
: this.renderField(field, parent, this.onChangeField),
|
||||
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', {
|
||||
class: 'jsoneditor-field' + (hasParent ? '' : ' jsoneditor-readonly'),
|
||||
contentEditable: hasParent,
|
||||
spellCheck: "false", // FIXME: turning off spellcheck doesn't work
|
||||
spellCheck: 'false',
|
||||
onBlur: onChangeField
|
||||
}, content)
|
||||
}
|
||||
|
@ -108,7 +107,7 @@ export default class JSONNode extends Component {
|
|||
return h('div', {class: 'jsoneditor-separator'}, ':')
|
||||
}
|
||||
|
||||
renderValue (value, onChangeValue) {
|
||||
renderValue (value, onChangeValue, onClickUrl, onKeyDownUrl) {
|
||||
const type = valueType (value)
|
||||
const _isUrl = isUrl(value)
|
||||
const valueClass = 'jsoneditor-value jsoneditor-' + type + (_isUrl ? ' jsoneditor-url' : '')
|
||||
|
@ -116,10 +115,10 @@ export default class JSONNode extends Component {
|
|||
return h('div', {
|
||||
class: valueClass,
|
||||
contentEditable: true,
|
||||
spellCheck: "false", // FIXME: turning off spellcheck doesn't work
|
||||
spellCheck: 'false', // FIXME: turning off spellcheck doesn't work
|
||||
onInput: onChangeValue,
|
||||
onClick: _isUrl ? this.onClickUrl : null,
|
||||
onKeyDown: _isUrl ? this.onKeyDownUrl: null,
|
||||
onClick: _isUrl ? onClickUrl : null,
|
||||
onKeyDown: _isUrl ? onKeyDownUrl: null,
|
||||
title: _isUrl ? 'Ctrl+Click or ctrl+Enter to open url' : null
|
||||
}, 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 util = require('../src/js/util');
|
||||
var util = require('./js/util');
|
||||
|
||||
// console.log('TEST', util.parsePath('.items[3].name'));
|
||||
// console.log('TEST', util.parsePath('.items[*].name'));
|
||||
|
|
Loading…
Reference in New Issue