@ryusei/light
Version:
<div align="center"> <a href="https://light.ryuseijs.com"> <img alt="RyuseiLight" src="https://light.ryuseijs.com/images/svg/logo.svg" width="70"> </a>
85 lines (71 loc) • 2.09 kB
text/typescript
import { PROJECT_CODE_SHORT } from '../../constants/project';
import { Renderer } from '../../core/Renderer/Renderer';
import { ACTIVE } from '../../constants/classes';
import { attr, error, isArray } from '../../utils';
/**
* The data attribute name for active lines.
* The value must be an array in JSON format, such as "[ 2, [ 5, 10 ] ]"
*
* @private
* @since 0.0.1
*/
export const ATTRIBUTE_ACTIVE_LINES = `data-${ PROJECT_CODE_SHORT }-active-lines`;
/**
* The component for highlighting lines.
*
* @since 0.0.1
*/
export function ActiveLines( { event, root, options }: Renderer ): void {
const lines = ( root && parseData( root ) ) || options.activeLines;
if ( isArray( lines ) ) {
const activeLines = normalize( lines );
event.on( 'gutter:row:open', ( html, classes, index ) => {
if ( activeLines[ index ] ) {
classes.push( activeLines[ index ] );
}
} );
event.on( 'line:open', ( html, classes, index ) => {
if ( activeLines[ index ] ) {
classes.push( activeLines[ index ] );
}
} );
}
}
/**
* Attempts to get definition of active lines from a data attribute.
*
* @param elm - A root element.
*
* @return An array with line numbers if available, or otherwise `undefined`.
*/
function parseData( elm: HTMLElement ): Array<number | [ number, number ]> | void {
const data = attr( elm, ATTRIBUTE_ACTIVE_LINES );
if ( data ) {
try {
return JSON.parse( data );
} catch ( e ) {
error( e.message );
}
}
}
/**
* Normalizes the definition of lines to activate.
*
* @param lines - An array with line numbers.
*
* @return An array with normalized line numbers.
*/
function normalize( lines: Array<number | [ number, number ]> ): string[] {
const numbers: string[] = [];
lines.forEach( range => {
if ( ! isArray( range ) ) {
range = [ range, range ];
}
const start = ( +range[ 0 ] || 1 ) - 1;
const end = ( +range[ 1 ] || 1 ) - 1;
for ( let i = start; i <= end; i++ ) {
numbers[ i ] = ACTIVE;
}
} );
return numbers;
}