Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 1x 1x 8x 1x 8x 8x 8x 8x 8x 8x 2x 2x 2x 2x 2x 1x 9x 9x 9x 31x 31x 31x 31x 11x 3x 11x 5x | import type { Plugin } from 'unified'; import type { Root, Element } from 'hast'; import { visit } from 'unist-util-visit'; import { detailsNode } from './detailsNode.js'; export type RehypeVideoOptions = { /** * URL suffix verification. * @default /\/(.*)(.mp4|.mov)$/ */ test?: RegExp; /** * Support `<details>` tag to wrap <video>. * @default true */ details?: boolean; } const properties = { muted: 'muted', controls: 'controls', style: 'max-height:640px;' }; const queryStringToObject = (url: string) => [...new URLSearchParams(url.split('?!#')[1])].reduce( (a: Record<string, string>, [k, v]) => ((a[k] = v), a), {} ); function reElement(node: Element, details: boolean, href: string) { const filename = href.split('/').pop()?.replace(/(\?|!|\#|$).+/, ''); node.properties = { ...properties, src: href }; node.tagName = 'video'; node.children = []; const { title = filename }= queryStringToObject(href); if (details) { const reNode = detailsNode(title); reNode.children.push({ ...node }); node.children = reNode.children; node.tagName = reNode.tagName; node.properties = reNode.properties; } } const RehypeVideo: Plugin<[RehypeVideoOptions?], Root> = (options) => { const { test = /\/(.*)(.mp4|.mov)$/, details = true } = options || {}; return (tree) => { visit(tree, 'element', (node, index, parent) => { const isChecked = (str: string) => test.test(str.replace(/(\?|!|\#|$).+/g, '').toLocaleLowerCase()) const child = node.children[0]; const delimiter = /((?:https?:\/\/)(?:(?:[a-z0-9]?(?:[a-z0-9\-]{1,61}[a-z0-9])?\.[^\.|\s])+[a-z\.]*[a-z]+|(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3})(?::\d{1,5})*[a-z0-9.,_\/~#&=;%+?\-\\(\\)]*)/g; // const delimiter = /((?:https?:\/\/)?(?:(?:[a-z0-9]?(?:[a-z0-9\-]{1,61}[a-z0-9])?\.[^\.|\s])+[a-z\.]*[a-z]+|(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3})(?::\d{1,5})*[a-z0-9.,_\/~#&=;%+?\-\\(\\)]*)/g; if (node.tagName === 'p' && node.children.length === 1) { if (child.type === 'text' && delimiter.test(child.value) && isChecked(child.value)) { reElement(node, details, child.value); } if (child.type === 'element' && child.tagName === 'a' && child.properties && typeof child.properties.href === 'string' && isChecked(child.properties.href)) { reElement(node, details, child.properties.href); } } }); } } export default RehypeVideo; |