@ryusei/code
Version:
<div align="center"> <a href="https://code.ryuseijs.com"> <img alt="RyuseiCode" src="https://code.ryuseijs.com/images/svg/logo.svg" width="70"> </a>
120 lines (105 loc) • 3.33 kB
text/typescript
import { AnyFunction, Options } from '@ryusei/code';
import { LINE_BREAK } from '../../constants/characters';
import { EVENT_MOUNT } from '../../constants/events';
import { Editor } from '../../core/Editor/Editor';
import { RyuseiCode } from '../../core/RyuseiCode/RyuseiCode';
import { count, isUndefined } from '../../utils';
import { EDITOR_HEIGHT, EDITOR_WIDTH, LINE_HEIGHT } from '../fixtures';
/**
* Creates a new editor instance and applies it to the pre element.
*
* @param code - Optional. The initial code.
* @param options - Optional. Options.
* @param tag - Optional. A tag for the source element.
*
* @return An Editor instance.
*/
export function init( code = '', options: Options = {}, tag = 'pre' ): Editor {
const ryuseiCode = new RyuseiCode( options );
const Editor = ryuseiCode.Editor;
document.head.innerHTML = '';
document.body.innerHTML = `<${ tag }>${ code }</${ tag }>`;
Editor.event.on( EVENT_MOUNT, () => {
const { elements } = Editor;
// Forcibly sets the height of the scroller.
Object.defineProperty( elements.scroller, 'clientHeight', { value: EDITOR_HEIGHT, writable: true } );
elements.editor.style.lineHeight = `${ LINE_HEIGHT }px`;
// Mocks the DOMRect.
elements.editor.getBoundingClientRect = elements.scroller.getBoundingClientRect = () => {
return {
top : 0,
right : EDITOR_WIDTH,
bottom: EDITOR_HEIGHT,
left : 0,
width : EDITOR_WIDTH,
height: EDITOR_HEIGHT,
x : 0,
y : EDITOR_HEIGHT,
toJSON: () => '',
};
};
} );
Editor.apply( tag );
return Editor;
}
/**
* Clears the editor and sets the provided new code.
*
* @param Editor - The Editor instance to clear.
* @param code - The new code.
*/
export function refresh( Editor: Editor, code = '' ): void {
const { Code } = Editor.Components;
const { lines, Sync } = Code;
lines.delete( 0, lines.length );
Code.value = code;
Sync.sync( 0, count( code, LINE_BREAK ) );
}
/**
* Generates huge code, starting from 0.
*
* @param length - A number of lines to generate.
* @param text - Optional. A test for all lines.
*
* @return Generated code.
*/
export function generate( length: number, text?: string ): string {
return Array.from( { length } ).map( ( item, index ) => isUndefined( text ) ? index : text ).join( LINE_BREAK );
}
/**
* Requests an animation frame and returns a Promise instance.
*
* @param callback - A callback function.
*
* @return A Promise instance.
*/
export function raf( callback: FrameRequestCallback ): Promise<void> {
return new Promise( resolve => {
requestAnimationFrame( () => {
resolve( callback( 0 ) );
} );
} );
}
/**
* Sets a timer with returning a Promise instance.
*
* @param callback - A callback function.
* @param time - A timer duration.
*
* @return A Promise instance.
*/
export function timer<T extends AnyFunction>( callback: T, time = 0 ): Promise<ReturnType<T>> {
return new Promise( resolve => {
setTimeout( () => {
resolve( callback() );
}, time );
} );
}
/**
* A promise that will be resolved on the next animation frame.
*
* @return A promise instance.
*/
export function waitForAnimationFrame(): Promise<void> {
return raf( () => 0 );
}