reprism
Version:
Modular Syntax highlighting for the web
275 lines (260 loc) • 10.5 kB
JavaScript
export default {
language: 'asciidoc',
init: Prism => {
(function (Prism) {
const attributes = {
pattern: /(^[ \t]*)\[(?!\[)(?:(["'$`])(?:(?!\2)[^\\]|\\.)*\2|\[(?:[^\]\\]|\\.)*\]|[^\]\\]|\\.)*\]/m,
lookbehind: true,
inside: {
quoted: {
pattern: /([$`])(?:(?!\1)[^\\]|\\.)*\1/,
inside: {
punctuation: /^[$`]|[$`]$/,
},
},
interpreted: {
pattern: /'(?:[^'\\]|\\.)*'/,
inside: {
punctuation: /^'|'$/,
// See rest below
},
},
string: /"(?:[^"\\]|\\.)*"/,
variable: /\w+(?==)/,
punctuation: /^\[|\]$|,/,
operator: /=/,
// The negative look-ahead prevents blank matches
'attr-value': /(?!^\s+$).+/,
},
}
Prism.languages.asciidoc = {
'comment-block': {
pattern: /^(\/{4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1/m,
alias: 'comment',
},
table: {
pattern: /^\|={3,}(?:(?:\r?\n|\r).*)*?(?:\r?\n|\r)\|={3,}$/m,
inside: {
specifiers: {
pattern: /(?!\|)(?:(?:(?:\d+(?:\.\d+)?|\.\d+)[+*])?(?:[<^>](?:\.[<^>])?|\.[<^>])?[a-z]*)(?=\|)/,
alias: 'attr-value',
},
punctuation: {
pattern: /(^|[^\\])[|!]=*/,
lookbehind: true,
},
// See rest below
},
},
'passthrough-block': {
pattern: /^(\+{4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1$/m,
inside: {
punctuation: /^\++|\++$/,
// See rest below
},
},
// Literal blocks and listing blocks
'literal-block': {
pattern: /^(-{4,}|\.{4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1$/m,
inside: {
punctuation: /^(?:-+|\.+)|(?:-+|\.+)$/,
// See rest below
},
},
// Sidebar blocks, quote blocks, example blocks and open blocks
'other-block': {
pattern: /^(--|\*{4,}|_{4,}|={4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1$/m,
inside: {
punctuation: /^(?:-+|\*+|_+|=+)|(?:-+|\*+|_+|=+)$/,
// See rest below
},
},
// list-punctuation and list-label must appear before indented-block
'list-punctuation': {
pattern: /(^[ \t]*)(?:-|\*{1,5}|\.{1,5}|(?:[a-z]|\d+)\.|[xvi]+\))(?= )/im,
lookbehind: true,
alias: 'punctuation',
},
'list-label': {
pattern: /(^[ \t]*)[a-z\d].+(?::{2,4}|;;)(?=\s)/im,
lookbehind: true,
alias: 'symbol',
},
'indented-block': {
pattern: /((\r?\n|\r)\2)([ \t]+)\S.*(?:(?:\r?\n|\r)\3.+)*(?=\2{2}|$)/,
lookbehind: true,
},
comment: /^\/\/.*/m,
title: {
pattern: /^.+(?:\r?\n|\r)(?:={3,}|-{3,}|~{3,}|\^{3,}|\+{3,})$|^={1,5} +.+|^\.(?![\s.]).*/m,
alias: 'important',
inside: {
punctuation: /^(?:\.|=+)|(?:=+|-+|~+|\^+|\++)$/,
// See rest below
},
},
'attribute-entry': {
pattern: /^:[^:\r\n]+:(?: .*?(?: \+(?:\r?\n|\r).*?)*)?$/m,
alias: 'tag',
},
attributes,
hr: {
pattern: /^'{3,}$/m,
alias: 'punctuation',
},
'page-break': {
pattern: /^<{3,}$/m,
alias: 'punctuation',
},
admonition: {
pattern: /^(?:TIP|NOTE|IMPORTANT|WARNING|CAUTION):/m,
alias: 'keyword',
},
callout: [
{
pattern: /(^[ \t]*)<?\d*>/m,
lookbehind: true,
alias: 'symbol',
},
{
pattern: /<\d+>/,
alias: 'symbol',
},
],
macro: {
pattern: /\b[a-z\d][a-z\d-]*::?(?:(?:\S+)??\[(?:[^\]\\"]|(["'])(?:(?!\1)[^\\]|\\.)*\1|\\.)*\])/,
inside: {
function: /^[a-z\d-]+(?=:)/,
punctuation: /^::?/,
attributes: {
pattern: /(?:\[(?:[^\]\\"]|(["'])(?:(?!\1)[^\\]|\\.)*\1|\\.)*\])/,
inside: attributes.inside,
},
},
},
inline: {
/*
The initial look-behind prevents the highlighting of escaped quoted text.
Quoted text can be multi-line but cannot span an empty line.
All quoted text can have attributes before [foobar, 'foobar', baz="bar"].
First, we handle the constrained quotes.
Those must be bounded by non-word chars and cannot have spaces between the delimiter and the first char.
They are, in order: _emphasis_, ``double quotes'', `single quotes', `monospace`, 'emphasis', *strong*, +monospace+ and #unquoted#
Then we handle the unconstrained quotes.
Those do not have the restrictions of the constrained quotes.
They are, in order: __emphasis__, **strong**, ++monospace++, +++passthrough+++, ##unquoted##, $$passthrough$$, ~subscript~, ^superscript^, {attribute-reference}, [[anchor]], [[[bibliography anchor]]], <<xref>>, (((indexes))) and ((indexes))
*/
pattern: /(^|[^\\])(?:(?:\B\[(?:[^\]\\"]|(["'])(?:(?!\2)[^\\]|\\.)*\2|\\.)*\])?(?:\b_(?!\s)(?: _|[^_\\\r\n]|\\.)+(?:(?:\r?\n|\r)(?: _|[^_\\\r\n]|\\.)+)*_\b|\B``(?!\s).+?(?:(?:\r?\n|\r).+?)*''\B|\B`(?!\s)(?: ['`]|.)+?(?:(?:\r?\n|\r)(?: ['`]|.)+?)*['`]\B|\B(['*+#])(?!\s)(?: \3|(?!\3)[^\\\r\n]|\\.)+(?:(?:\r?\n|\r)(?: \3|(?!\3)[^\\\r\n]|\\.)+)*\3\B)|(?:\[(?:[^\]\\"]|(["'])(?:(?!\4)[^\\]|\\.)*\4|\\.)*\])?(?:(__|\*\*|\+\+\+?|##|\$\$|[~^]).+?(?:(?:\r?\n|\r).+?)*\5|\{[^}\r\n]+\}|\[\[\[?.+?(?:(?:\r?\n|\r).+?)*\]?\]\]|<<.+?(?:(?:\r?\n|\r).+?)*>>|\(\(\(?.+?(?:(?:\r?\n|\r).+?)*\)?\)\)))/m,
lookbehind: true,
inside: {
attributes,
url: {
pattern: /^(?:\[\[\[?.+?\]?\]\]|<<.+?>>)$/,
inside: {
punctuation: /^(?:\[\[\[?|<<)|(?:\]\]\]?|>>)$/,
},
},
'attribute-ref': {
pattern: /^\{.+\}$/,
inside: {
variable: {
pattern: /(^\{)[a-z\d,+_-]+/,
lookbehind: true,
},
operator: /^[=?!#%@$]|!(?=[:}])/,
punctuation: /^\{|\}$|::?/,
},
},
italic: {
pattern: /^(['_])[\s\S]+\1$/,
inside: {
punctuation: /^(?:''?|__?)|(?:''?|__?)$/,
},
},
bold: {
pattern: /^\*[\s\S]+\*$/,
inside: {
punctuation: /^\*\*?|\*\*?$/,
},
},
punctuation: /^(?:``?|\+{1,3}|##?|\$\$|[~^]|\(\(\(?)|(?:''?|\+{1,3}|##?|\$\$|[~^`]|\)?\)\))$/,
},
},
replacement: {
pattern: /\((?:C|TM|R)\)/,
alias: 'builtin',
},
entity: /&#?[\da-z]{1,8};/i,
'line-continuation': {
pattern: /(^| )\+$/m,
lookbehind: true,
alias: 'punctuation',
},
}
// Allow some nesting. There is no recursion though, so cloning should not be needed.
attributes.inside.interpreted.inside.rest = {
macro: Prism.languages.asciidoc.macro,
inline: Prism.languages.asciidoc.inline,
replacement: Prism.languages.asciidoc.replacement,
entity: Prism.languages.asciidoc.entity,
}
Prism.languages.asciidoc['passthrough-block'].inside.rest = {
macro: Prism.languages.asciidoc.macro,
}
Prism.languages.asciidoc['literal-block'].inside.rest = {
callout: Prism.languages.asciidoc.callout,
}
Prism.languages.asciidoc.table.inside.rest = {
'comment-block': Prism.languages.asciidoc['comment-block'],
'passthrough-block': Prism.languages.asciidoc['passthrough-block'],
'literal-block': Prism.languages.asciidoc['literal-block'],
'other-block': Prism.languages.asciidoc['other-block'],
'list-punctuation': Prism.languages.asciidoc['list-punctuation'],
'indented-block': Prism.languages.asciidoc['indented-block'],
comment: Prism.languages.asciidoc.comment,
title: Prism.languages.asciidoc.title,
'attribute-entry': Prism.languages.asciidoc['attribute-entry'],
attributes: Prism.languages.asciidoc.attributes,
hr: Prism.languages.asciidoc.hr,
'page-break': Prism.languages.asciidoc['page-break'],
admonition: Prism.languages.asciidoc.admonition,
'list-label': Prism.languages.asciidoc['list-label'],
callout: Prism.languages.asciidoc.callout,
macro: Prism.languages.asciidoc.macro,
inline: Prism.languages.asciidoc.inline,
replacement: Prism.languages.asciidoc.replacement,
entity: Prism.languages.asciidoc.entity,
'line-continuation': Prism.languages.asciidoc['line-continuation'],
}
Prism.languages.asciidoc['other-block'].inside.rest = {
table: Prism.languages.asciidoc.table,
'list-punctuation': Prism.languages.asciidoc['list-punctuation'],
'indented-block': Prism.languages.asciidoc['indented-block'],
comment: Prism.languages.asciidoc.comment,
'attribute-entry': Prism.languages.asciidoc['attribute-entry'],
attributes: Prism.languages.asciidoc.attributes,
hr: Prism.languages.asciidoc.hr,
'page-break': Prism.languages.asciidoc['page-break'],
admonition: Prism.languages.asciidoc.admonition,
'list-label': Prism.languages.asciidoc['list-label'],
macro: Prism.languages.asciidoc.macro,
inline: Prism.languages.asciidoc.inline,
replacement: Prism.languages.asciidoc.replacement,
entity: Prism.languages.asciidoc.entity,
'line-continuation': Prism.languages.asciidoc['line-continuation'],
}
Prism.languages.asciidoc.title.inside.rest = {
macro: Prism.languages.asciidoc.macro,
inline: Prism.languages.asciidoc.inline,
replacement: Prism.languages.asciidoc.replacement,
entity: Prism.languages.asciidoc.entity,
}
// Plugin to make entity title show the real entity, idea by Roman Komarov
Prism.hooks.add('wrap', env => {
if (env.type === 'entity') {
env.attributes.title = env.content.replace(/&/, '&')
}
})
}(Prism))
},
}