UNPKG

vue-highlight-words

Version:

Vue component to highlight words within a larger body of text

97 lines (91 loc) 3.02 kB
/*! * vue-highlight-words v3.0.1 * © 2022 Yichang Liu * LICENCE: MIT */ import { findAll } from 'highlight-words-core'; import { h } from 'vue'; const VueHighlightWordsImpl = (props, context) => { const chunks = findAll({ autoEscape: props.autoEscape, caseSensitive: props.caseSensitive, findChunks: props.findChunks, sanitize: props.sanitize, searchWords: props.searchWords, textToHighlight: props.textToHighlight, }); const children = getTextChildren(props, chunks); const slots = context.slots; if (slots.default) { return slots.default && slots.default(children); } return h('span', { ...context.attrs }, children.map(({ chunk, text, attrs }) => { if (!chunk.highlight) { return text; } return h('mark', attrs, [text]); })); }; const EMPTY_STYLE = {}; function getTextChildren(props, chunks) { let highlightCount = -1; let highlightClassNames = ''; let highlightStyles = {}; const { textToHighlight, highlightClassName, highlightStyle = EMPTY_STYLE, activeIndex, activeClassName, activeStyle = EMPTY_STYLE, } = props; return chunks.map((chunk, index) => { const text = textToHighlight.substr(chunk.start, chunk.end - chunk.start); if (!chunk.highlight) { return { chunk, text }; } else { highlightCount++; // start at 0 const isActive = highlightCount === +(activeIndex || -1); highlightClassNames = `${highlightClassName} ${isActive ? activeClassName : ''}`; highlightStyles = isActive === true && activeStyle != null ? { ...highlightStyle, ...activeStyle } : highlightStyle; const attrs = { class: highlightClassNames, key: index, style: highlightStyles, highlightIndex: highlightCount, }; return { chunk, text, attrs }; } }); } VueHighlightWordsImpl.props = { activeClassName: String, activeIndex: Number, activeStyle: Object, autoEscape: Boolean, caseSensitive: { type: Boolean, defualt: false, }, findChunks: Function, custom: { type: Boolean, default: false, }, highlightClassName: String, highlightStyle: Object, sanitize: Function, searchWords: { type: Array, validator(value) { return value.every((word) => typeof word === 'string'); }, required: true, }, textToHighlight: { type: String, required: true, }, }; const VueHighlightWords = VueHighlightWordsImpl; function install(app, options = { name: '' }) { app.component(options.name || 'VueHighlightWords', VueHighlightWords); } export { VueHighlightWords, VueHighlightWords as default, install };