/** * @[caniuse embed{1,2,3,4}](feature_name) * @[caniuse image](feature_name) */ import type { PluginWithOptions } from 'markdown-it' import type MarkdownIt from 'markdown-it' import type Token from 'markdown-it/lib/token.mjs' import type { CanIUseMode, CanIUseOptions, CanIUseTokenMeta } from '../../shared/index.js' import container from 'markdown-it-container' import { customAlphabet } from 'nanoid' import { createRuleBlock } from '../utils/createRuleBlock.js' const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 5) const UNDERLINE_RE = /_+/g /** * @example * ```md * @[caniuse](feature_name) * ``` */ export const caniusePlugin: PluginWithOptions = ( md, { mode: defaultMode = 'embed' }: CanIUseOptions = {}, ): void => { createRuleBlock(md, { type: 'caniuse', syntaxPattern: /^@\[caniuse\s*(embed|image)?(?:\{([0-9,\-]*)\})?\]\(([^)]*)\)/, meta: ([, mode, versions = '', feature]) => ({ feature, mode: (mode as CanIUseMode) || defaultMode, versions, }), content: meta => resolveCanIUse(meta), }) } /** * @deprecated use caniuse plugin * * 兼容旧语法 * @example * ```md * :::caniuse * ::: * ``` */ export function legacyCaniuse( md: MarkdownIt, { mode = 'embed' }: CanIUseOptions = {}, ): void { const modeMap: CanIUseMode[] = ['image', 'embed'] const isMode = (mode: CanIUseMode): boolean => modeMap.includes(mode) mode = isMode(mode) ? mode : modeMap[0] const type = 'caniuse' const validateReg = new RegExp(`^${type}`) const validate = (info: string): boolean => { return validateReg.test(info.trim()) } const render = (tokens: Token[], index: number): string => { const token = tokens[index] if (token.nesting === 1) { const info = token.info.trim().slice(type.length).trim() || '' const feature = info.split(/\s+/)[0] const versions = info.match(/\{(.*)\}/)?.[1] || '' return feature ? resolveCanIUse({ feature, mode, versions }) : '' } else { return '' } } md.use(container, type, { validate, render }) } function resolveCanIUse({ feature, mode, versions }: CanIUseTokenMeta): string { if (!feature) return '' if (mode === 'image') { const link = 'https://caniuse.bitsofco.de/image/' const alt = `Data on support for the ${feature} feature across the major browsers from caniuse.com` return `

${alt}

` } feature = feature.replace(UNDERLINE_RE, '_') const { past, future } = resolveVersions(versions) const meta = nanoid() return `` } function resolveVersions(versions: string): { past: number, future: number } { if (!versions) return { past: 2, future: 1 } const list = versions .split(',') .map(v => Number(v.trim())) .filter(v => !Number.isNaN(v) && v >= -5 && v <= 3) list.push(0) const uniq = [...new Set(list)].sort((a, b) => b - a) return { future: uniq[0], past: Math.abs(uniq[uniq.length - 1]), } }