diff --git a/src/JSONNode.svelte b/src/JSONNode.svelte index 1d6dab7..6834562 100644 --- a/src/JSONNode.svelte +++ b/src/JSONNode.svelte @@ -7,6 +7,7 @@ import { escapeHTML } from './utils/stringUtils.js' import { updateProps } from './utils/updateProps.js' import { unescapeHTML } from './utils/stringUtils' + import { getInnerText } from './utils/domUtils' export let key = undefined export let value @@ -41,6 +42,13 @@ $: escapedValue = escapeHTML(value, escapeUnicode) $: valueIsUrl = isUrl(value) + $: keyClass = classnames('key', { + empty: escapedKey.length === 0, + search: searchResult + ? !!searchResult[SEARCH_PROPERTY] + : false + }) + $: valueClass = classnames('value', type, { url: valueIsUrl, empty: escapedValue.length === 0, @@ -54,12 +62,12 @@ } function handleKeyInput (event) { - const newKey = unescapeHTML(event.target.innerText) + const newKey = unescapeHTML(getInnerText(event.target)) onChangeKey(newKey, key) } function handleValueInput (event) { - const valueText = unescapeHTML(event.target.innerText) + const valueText = unescapeHTML(getInnerText(event.target)) const newValue = stringConvert(valueText) // TODO: implement support for type "string" onChangeValue(newValue, key) } @@ -140,7 +148,7 @@ {#if typeof key === 'string'}
{#if typeof key === 'string'}
{#if typeof key === 'string'}
* { + display: table-cell; + } } .contents { @@ -296,8 +308,6 @@ .key, .value { - display: table-cell; - line-height: $line-height; min-width: 16px; word-break: normal; @@ -314,13 +324,11 @@ .separator, .delimiter { - display: table-cell; vertical-align: top; color: $gray; } .tag { - display: table-cell; vertical-align: top; border: none; font-size: $font-size-small; @@ -388,10 +396,9 @@ div.empty::after { pointer-events: none; color: lightgray; - font-size: 8pt; } - div.property.empty::after { + div.key.empty::after { content: 'key'; } diff --git a/src/utils/domUtils.js b/src/utils/domUtils.js new file mode 100644 index 0000000..62bf215 --- /dev/null +++ b/src/utils/domUtils.js @@ -0,0 +1,71 @@ +/** + * Get the inner text of an HTML element (for example a div element) + * @param {Element} element + * @param {Object} [buffer] + * @return {String} innerText + */ +export function getInnerText (element, buffer) { + const first = (buffer === undefined) + if (first) { + buffer = { + 'text': '', + 'flush': function () { + const text = this.text + this.text = '' + return text + }, + 'set': function (text) { + this.text = text + } + } + } + + // text node + if (element.nodeValue) { + return buffer.flush() + element.nodeValue + } + + // divs or other HTML elements + if (element.hasChildNodes()) { + const childNodes = element.childNodes + let innerText = '' + + for (let i = 0, iMax = childNodes.length; i < iMax; i++) { + const child = childNodes[i] + + if (child.nodeName === 'DIV' || child.nodeName === 'P') { + const prevChild = childNodes[i - 1] + const prevName = prevChild ? prevChild.nodeName : undefined + if (prevName && prevName !== 'DIV' && prevName !== 'P' && prevName !== 'BR') { + innerText += '\n' + buffer.flush() + } + innerText += getInnerText(child, buffer) + buffer.set('\n') + } + else if (child.nodeName === 'BR') { + innerText += buffer.flush() + buffer.set('\n') + } + else { + innerText += getInnerText(child, buffer) + } + } + + return innerText + } + else { + if (element.nodeName === 'P' && getInternetExplorerVersion() !== -1) { + // On Internet Explorer, a

with hasChildNodes()==false is + // rendered with a new line. Note that a

with + // hasChildNodes()==true is rendered without a new line + // Other browsers always ensure there is a
inside the

, + // and if not, the

does not render a new line + return buffer.flush() + } + } + + // br or unknown + return '' + } + \ No newline at end of file