Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Takes a list of intervals with values and a string and chops up the string into a structured object containing those values.
"use strict"
const message = `The quick brown fox jumped over the lazy dog. What a jerk!`;
const intervals = [
[ 25, 32, 'strong' ],
[ 5, 9, 'a' ],
[ 26, 29, 'span' ],
[ 0, 0, 'img' ],
[ 32, 37, 'em' ],
[ 12, 48, 'blockquote' ],
[ 44, 44, 'badge' ]
];
const nodeSort = (a, b) => {
if ( a.s < b.s ) return -1;
if ( b.s < a.s ) return 1;
return b.e - a.e;
}
const addNode = ( nodes, node ) => {
if ( 0 === node.s && 0 === node.e ) return [ ...nodes, node ];
const parent= nodes.findIndex( p => p.s <= node.s && p.e >= node.e );
if ( -1 === parent ) return [ ...nodes, node ];
return [
...nodes.slice( 0, parent),
Object.assign( nodes[ parent ], {
c: addNode( nodes[ parent ].c, node )
} ),
...nodes.slice( parent + 1 )
];
}
const buildNestedList = intervals => intervals
.map( i => ( { s: i[0], e: i[1], v: i[2], c: [] } ) )
.sort( nodeSort )
.reduce( addNode, [] );
const parse = ( total, nextNode ) => {
const prev = total[0];
const text = total[1];
const offset = total[2];
const s = nextNode.s - offset;
const e = nextNode.e - offset;
const preText = ( s > 0 ) ? [ text.slice( 0, s ) ] : [];
const children = nextNode.c.reduce( parse, [ [], text.slice( s, e ), nextNode.s ] );
const parsed = {
type: nextNode.v,
children: [ ...children[ 0 ], children[ 1 ] ].filter( x => x ),
};
return [ [ ...prev, ...preText, parsed ], text.slice( e ), nextNode.e ];
}
const parsed = buildNestedList( intervals ).reduce( parse, [ [], message, 0 ] );
console.log( JSON.stringify( [ ...parsed[ 0 ], parsed[ 1 ] ] ) );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment