JSON String Extractor
by xowap
HTML
<div id="app">
<h1>JSON string extractor</h1>
<h2>Input</h2>
<div class="field">
<label for="input">Input code</label>
<textarea v-model="input" id="input" cols="50" rows="10" @input="resizeInput()"></textarea>
</div>
<h2>Output</h2>
<div class="output" v-for="(string, index) of output" :key="index">
<h3>String #{{ index }}</h3>
<pre>{{ string }}</pre>
</div>
</div>
SASS
@import url('https://fonts.googleapis.com/css?family=Heebo|Inconsolata|Noto+Serif:700');
$body-padding: 20px
body
font-family: 'Heebo', sans-serif
font-size: 16px
padding: 0 $body-padding $body-padding $body-padding
h1, h2, h3
font-family: 'Noto Serif', serif
font-weight: bold
h1
font-size: 28px
margin: 30px 0
h2
font-size: 24px
margin: 20px 0
h3
font-size: 20px
margin: 10px 0
textarea, pre
font-family: 'Inconsolata', monospace
pre
background-color: #ccc
padding: 15px (15px + $body-padding)
margin: 0 (- $body-padding)
label
position: absolute
overflow: hidden
width: 0
height: 0
textarea
background-color: #eee
margin: 0 (- $body-padding)
padding: 15px (15px + $body-padding)
height: 0
border: 0
box-sizing: border-box
resize: none
&:hover,
&:focus
background-color: #ccc;
.field
display: flex
flex-direction: column
JavaScript
function findStrings(string) {
const re = /"(([^\0-\x19"\\]|\\[^\0-\x19])*)"/g;
const out = [];
while ((m = re.exec(string)) !== null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
out.push(m[1]);
}
return out;
}
function subEscapes(string) {
const re = /\\(["\\\/bnrt]|u([a-fA-F0-9]{4}))/g;
const map = {
'"': '"',
'\\': '\\',
'/': '/',
'b': '\b',
'n': '\n',
'r': '\r',
't': '\t',
};
return string.replace(re, (_, char, hexCodePoint) => {
if (char[0] === 'u') {
return String.fromCodePoint(parseInt(hexCodePoint, 16));
} else {
return map[char];
}
})
}
const app = new Vue({
el: '#app',
data() {
return {
input: `const foo = "say \\"foo\\" \\ud83e\\udd37";`,
};
},
methods: {
resizeInput() {
const ta = this.$el.querySelector('textarea');
ta.style.setProperty('height', '0');
const height = ta.scrollHeight;
ta.style.setProperty('height', `${height}px`);
},
},
computed: {
output() {
return findStrings(this.input).map(subEscapes);
},
},
mounted() {
this.resizeInput();
},
});