UNPKG

unified-doc-dom

Version:
325 lines (273 loc) 8.93 kB
# unified-doc-dom DOM APIs for [**unified-doc**][unified-doc]. --- ## Install ```sh npm install unified-doc-dom ``` ## Use ```js import Doc from 'unified-doc'; import { fromFile, highlight, registerMarks, saveFile, selectText } from 'unified-doc-dom'; // optionally import provided css highlight effects, or specify your own import 'unified-doc-dom/css/highlight.css'; const file = new File(...); const marks: [ { id: 'a', start: 0, end: 5 }, { id: 'b', start: 7, end: 10 }, ]; // prepare data from file and initialize a doc instance const fileData = await fromFile(file); const doc = Doc({ content: fileData.content, filename: fileData.name, marks, }); // save files in different format function saveAsHtml() { saveFile(doc.file('.html')); } function saveAsText() { saveFile(doc.file('.txt')); } // render the document and retrieve the docElement DOM element const docElement = ... // via doc.compile() // register click events and custom tooltip implementations with registerMarks function createTooltip(event, mark) {...} function destroyTooltip(event, mark) {...} function register() { registerMarks(docElement, marks, { onClick: (event, mark) => console.log(mark.id), onMouseEnter: (event, mark) => createTooltip(event, mark), onMouseLeave: (event, mark) => destroyTooltip(event, mark), }) } // highlights a mark (e.g. triggered from a button's click event) function highlightMark(markId) { const cleanup = highlight(docElement, markId); // use the cleanup function appropriately in a controlled manner } // update/add marks on text selection function register() { function callback(selectedText) { marks.push(selectedText); } const cleanup = selectText(docElement, { callback }); // use the cleanup function appropriately in a controlled manner } ``` ## API - [`fromFile(file)`](#fromFilefile) - [`toFile(fileData)`](#toFilefileData) - [`saveFile(fileData)`](#saveFilefileData) - [`highlight(docElement, elementId[, options])`](#highlightdocElement-elementId-options) - [`registerMarks(docElement, marks, callbacks)`](#registerMarksdocElement-marks-callbacks) - [`selectText(docElement[, options])`](#selectTextdocElement-options) The term `doc` used below refers to a `unified-doc` instance. Please refer to [**unified-doc**][unified-doc] for detailed documentation of `doc` API methods. ### `fromFile(file)` #### Interface ```ts function fromFile(file: File): Promise<FileData> ``` Returns `FileData` from a JS `File`. Can only be used **asynchronously**. This method is useful to prepare file data that will be passed to `unified-doc` during initialization (e.g. `name`, `content`). #### Example ```js import { fromFile } from 'unified-doc-dom'; const file = File(['> some **strong** content'], 'doc.md', { type: 'text/markdown' }); const fileData = await fromFile(file); expect(fileData).toEqual({ content: '> some **strong** content', extension: '.md', name: 'doc.md', stem: 'doc', type: 'text/markdown', }); ``` ### `toFile(fileData)` #### Interface ```ts function toFile(fileData: FileData): File; ``` Returns a JS `File` from `FileData`. This method is useful to convert file data into a JS `File` object. When used together with `doc.file()`, this is an easy way to retrieve file representations in supported formats. #### Example ```js import { toFile } from 'unified-doc-dom'; import Doc from 'unified-doc'; const doc = Doc({ content: '> some **strong** content', filename: 'doc.md', }) expect(toFile(doc.file('.txt'))) .toEqual(File( ['some strong content'], 'doc.txt', { type: 'text/plain' }, )); expect(toFile(doc.file('.html'))) .toEqual(File( ['<blockquote>some <strong>strong</strong> content<blockquote>'], 'doc.html', { type: 'text/html' } )); ``` ### `saveFile(fileData)` #### Interface ```ts function saveFile(fileData: FileData): void; ``` Saves a JS `File` from `FileData`. Implemented using the [`file-saver`][file-saver] package and `toFile` method. This method is useful to save the file data returned by the `doc.file()`. #### Example ```js import { saveFile } from 'unified-doc-dom'; import Doc from 'unified-doc'; const doc = Doc({ content: '> some **strong** content', filename: 'doc.md', }) function saveAsSource() { saveFile(doc.file()); } function saveAsHtml() { saveFile(doc.file('.html')); } function saveAsText() { saveFile(doc.file('.txt')); } ``` #### Related interfaces ```ts interface FileData { /** file content in string form */ content: string; /** file extension (includes preceding '.') */ extension: string; /** file name (includes extension) */ name: string; /** file name (without extension) */ stem: string; /** mime type of file */ type: string; } ``` ### `highlight(docElement, elementId[, options])` #### Interface ```ts function highlight( /** document DOM element rendered by `unified-doc` */ docElement: HTMLElement, /** target element ID of interest */ elementId: string, /** options to configure `highlight` behavior */ options?: HighlightOptions, ): () => void; ``` Highlights all elements that match a provided `elementId` under a `docElement` rendered by `unified-doc`. The highlighter draws a bounding box around all queried elements and removes itself after a specified duration. The method returns a cleanup function that can be called appropriately. #### Example ```js import { highlight } from 'unified-doc-dom'; // optionally import provided css highlight effects, or specify your own import 'unified-doc-dom/css/highlight.css'; const docElement = ...; // document DOM element rendered by unified-doc const options = { background: 'rgba(255, 0, 0, 0.3)', durationMs: 4000, highlighterClassName: 'custom-highlighter', selector: elementId => `[data-mark-id='${elementId}']` }; function handleHighlightElement(elementId) { const cleanup = highlight(docElement, elementId, options); // you can use and call the cleanup method in a controlled way } ``` #### Related interfaces ```ts interface HighlightOptions { /** background color of the highlighter. A low opacity is recommended e.g. rgba(0, 0, 255, 0.2) */ background?: string; /** removes/fades the highlight after some elapsed duration (in ms) */ durationMs?: number; /** customize highlighter behaviors with optional CSS */ highlighterClassName?: string; /** custom `querySelector` pattern for selecting elements based on the provided `elementId` */ selector?: (elementId: string) => string; } ``` ### `registerMarks(docElement, marks, callbacks)` #### Interface ```ts function registerMarks( /** document DOM element rendered by `unified-doc` */ docElement: HTMLElement, /** array of `marks` data used by `unified-doc` **/ marks: Mark[], /** callbacks to apply to marked elements */ callbacks: MarkCallbacks, ); ``` Registers all `mark` elements with provided `callbacks` under a `docElement` rendered by `unified-doc`. #### Related interfaces ```ts interface Mark { /** unique ID for mark (required for mark algorithm to work) */ id: string; /** start offset of the mark relative to `textContent` of the `doc` */ start: number; /** end offset of the mark relative to `textContent` of the `doc` */ end: number; /** apply optional CSS classnames to marked nodes */ classNames?: string[]; /** apply optional dataset attributes (i.e. `data-*`) to marked nodes */ dataset?: Record<string, any>; /** contextual data can be stored here */ data?: Record<string, any>; /** apply optional styles to marked nodes */ style?: Record<string, any>; } type MarkCallback = (event: MouseEvent, mark: Mark) => void; interface MarkCallbacks { onClick?: MarkCallback; onMouseEnter?: MarkCallback; onMouseOut?: MarkCallback; } ``` ### `selectText(docElement[, options])` #### Interface ```ts function selectText( /** document DOM element rendered by `unified-doc` */ docElement: HTMLElement, /** options to configure `selectText` behavior */ options?: SelectTextOptions, ): () => void; ``` Capture selected text under the `docElement` rendered by `unified-doc`. Implemented using the [`rangy`][rangy] package. The selected text object is `Mark`-compatible, allowing easy integration with `marks` used by `unified-doc`. #### Related interfaces ```ts interface SelectedText { /** start offset of selected text relative to `textContent` of the `docElement` */ start: number; /** end offset of selected text relative to `textContent` of the `docElement` */ end: number; /** selected text value */ value: string; } interface SelectTextOptions { /** captures the `SelectedText` object in a callback */ callback?: (selectedText: SelectedText) => void; } ``` <!-- Definitions --> [unified-doc]: https://github.com/unified-doc/unified-doc [file-saver]: https://github.com/eligrey/FileSaver.js [rangy]: https://github.com/timdown/rangy