import htmlTags, { voidHtmlTags } from 'html-tags';
import { en } from '../locales/en';
export const VOID_HTML_TAGS = voidHtmlTags;
export const HTML_TAGS = htmlTags;
export const BLOCK_DOM_PROPERTY = '__MUYA_BLOCK__';
/**
* [genUpper2LowerKeyHash generate constants map hash, the value is lowercase of the key,
* also translate `_` to `-`]
*/
function genUpper2LowerKeyHash(keys: string[]): Record {
return keys.reduce((acc, key) => {
const value = key.toLowerCase().replace(/_/g, '-');
return Object.assign(acc, { [key]: value });
}, {});
}
/**
* generate constants map, the value is the key.
*/
function generateKeyHash(keys: string[]): Record {
return keys.reduce((acc, key) => {
return Object.assign(acc, { [key]: key });
}, {});
}
interface ITag {
open: string;
close: string;
}
export const FORMAT_MARKER_MAP: Record = {
em: '*',
inline_code: '`',
strong: '**',
del: '~~',
inline_math: '$',
};
export const FORMAT_TAG_MAP: Record = {
u: {
open: '',
close: '',
},
sub: {
open: '',
close: '',
},
sup: {
open: '',
close: '',
},
mark: {
open: '',
close: '',
},
};
export const FORMAT_TYPES = [
'strong',
'em',
'del',
'inline_code',
'link',
'image',
'inline_math',
];
export const PARAGRAPH_STATE = {
name: 'paragraph',
text: 'paragraph example',
};
export const THEMATIC_BREAK_STATE = {
name: 'thematic-break',
text: '---',
};
export const EVENT_KEYS = generateKeyHash([
'Enter',
'Backspace',
'Space',
'Delete',
'ArrowUp',
'ArrowDown',
'ArrowLeft',
'ArrowRight',
'Tab',
'Escape',
]);
// TODO remove unused classnames after muya stable.
export const CLASS_NAMES = genUpper2LowerKeyHash([
'MU_EDITOR',
'MU_ACTIVE',
'MU_AUTO_LINK',
'MU_AUTO_LINK_EXTENSION',
'MU_BACKLASH',
'MU_BUG',
'MU_BULLET_LIST',
'MU_BULLET_LIST_ITEM',
'MU_CHECKBOX_CHECKED',
'MU_CONTAINER_BLOCK',
'MU_CONTAINER_PREVIEW',
'MU_CONTAINER_ICON',
'MU_COPY_REMOVE',
'MU_DISABLE_HTML_RENDER',
'MU_EMOJI_MARKED_TEXT',
'MU_EMOJI_MARKER',
'MU_EMPTY',
'MU_FENCE_CODE',
'MU_FOCUS_MODE',
'MU_FRONT_MATTER',
'MU_FRONT_ICON',
'MU_GRAY',
'MU_HARD_LINE_BREAK',
'MU_HARD_LINE_BREAK_SPACE',
'MU_LINE_END',
'MU_HEADER_TIGHT_SPACE',
'MU_HIDE',
'MU_HIGHLIGHT',
'MU_HTML_BLOCK',
'MU_HTML_ESCAPE',
'MU_HTML_PREVIEW',
'MU_HTML_TAG',
'MU_IMAGE_FAIL',
'MU_IMAGE_BUTTONS',
'MU_IMAGE_LOADING',
'MU_EMPTY_IMAGE',
'MU_IMAGE_MARKED_TEXT',
'MU_IMAGE_SRC',
'MU_IMAGE_CONTAINER',
'MU_INLINE_IMAGE',
'MU_IMAGE_SUCCESS',
'MU_IMAGE_UPLOADING',
'MU_INLINE_IMAGE_SELECTED',
'MU_INLINE_IMAGE_IS_EDIT',
'MU_SMALL_IMAGE',
'MU_INDENT_CODE',
'MU_FOOTNOTE',
'MU_FOOTNOTE_INPUT',
'MU_FOOTNOTE_BACKLINK',
'MU_INLINE_FOOTNOTE_IDENTIFIER',
'MU_INLINE_RULE',
'MU_LANGUAGE',
'MU_LANGUAGE_INPUT',
'MU_LINK',
'MU_LINK_IN_BRACKET',
'MU_LIST_ITEM',
'MU_LOOSE_LIST_ITEM',
'MU_MATH',
'MU_MATH_TEXT',
'MU_MATH_RENDER',
'MU_RUBY',
'MU_RUBY_TEXT',
'MU_RUBY_RENDER',
'MU_SELECTED',
'MU_SOFT_LINE_BREAK',
'MU_MATH_ERROR',
'MU_MATH_MARKER',
'MU_MATH_RENDER',
'MU_MATH_TEXT',
'MU_MERMAID',
'MU_MULTIPLE_MATH',
'MU_NO_TEXT_LINK',
'MU_ORDER_LIST',
'MU_ORDER_LIST_ITEM',
'MU_OUTPUT_REMOVE',
'MU_PARAGRAPH',
'MU_RAW_HTML',
'MU_REFERENCE_LABEL',
'MU_REFERENCE_LINK',
'MU_REFERENCE_MARKER',
'MU_REFERENCE_TITLE',
'MU_REMOVE',
'MU_RUBY',
'MU_RUBY_RENDER',
'MU_RUBY_TEXT',
'MU_SELECTION',
'MU_SHOW_PREVIEW',
'MU_SOFT_LINE_BREAK',
'MU_TASK_LIST',
'MU_TASK_LIST_ITEM',
'MU_TASK_LIST_ITEM_CHECKBOX',
'MU_TIGHT_LIST_ITEM',
'MU_TOOL_BAR',
'MU_VEGA_LITE',
'MU_WARN',
'MU_SHOW_QUICK_INSERT_HINT',
]);
export const PARAGRAPH_TYPES = [
'p',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'blockquote',
'pre',
'ul',
'ol',
'li',
'figure',
];
export const BLOCK_TYPE6 = [
'address',
'article',
'aside',
'base',
'basefont',
'blockquote',
'body',
'caption',
'center',
'col',
'colgroup',
'dd',
'details',
'dialog',
'dir',
'div',
'dl',
'dt',
'fieldset',
'figcaption',
'figure',
'footer',
'form',
'frame',
'frameset',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'head',
'header',
'hr',
'html',
'iframe',
'legend',
'li',
'link',
'main',
'menu',
'menuitem',
'meta',
'nav',
'noframes',
'ol',
'optgroup',
'option',
'p',
'param',
'section',
'source',
'summary',
'table',
'tbody',
'td',
'tfoot',
'th',
'thead',
'title',
'tr',
'track',
'ul',
];
export const BRACKET_HASH: Record = {
'{': '}',
'[': ']',
'(': ')',
'*': '*',
'_': '_',
'"': '"',
'\'': '\'',
'$': '$',
'~': '~',
};
export const BACK_HASH: Record = {
'}': '{',
']': '[',
')': '(',
'*': '*',
'_': '_',
'"': '"',
'\'': '\'',
'$': '$',
'~': '~',
};
export const MUYA_DEFAULT_OPTIONS = {
fontSize: 16,
lineHeight: 1.6,
focusMode: false,
markdown: '',
// Whether to trim the beginning and ending empty line in code block when open markdown.
trimUnnecessaryCodeBlockEmptyLines: false,
preferLooseListItem: true,
autoPairBracket: true,
autoPairMarkdownSyntax: true,
autoPairQuote: true,
bulletListMarker: '-',
orderListDelimiter: '.',
tabSize: 4,
codeBlockLineNumbers: false,
// bullet/list marker width + listIndentation, tab or Daring Fireball Markdown (4 spaces) --> list indentation
listIndentation: 1,
frontmatterType: '-',
mermaidTheme: 'default', // dark / forest / default
vegaTheme: 'latimes', // excel / ggplot2 / quartz / vox / fivethirtyeight / dark / latimes
hideQuickInsertHint: false,
hideLinkPopup: false,
autoCheck: false,
// Whether we should set spellcheck attribute on our container to highlight misspelled words.
// NOTE: The browser is not able to correct misspelled words words without a custom
// implementation like in MarkText.
spellcheckEnabled: false,
// Markdown extensions
frontMatter: true, // Whether to support frontmatter.
superSubScript: true,
footnote: false,
// Whether math block is supported.
math: true,
isGitlabCompatibilityEnabled: true,
// Move checked task list item to the end of task list.
autoMoveCheckedToEnd: false,
// Whether HTML rendering is disabled or not.
disableHtml: false,
locale: en,
};
export const punctuation = [
'!',
'"',
'#',
'$',
'%',
'&',
'\'',
'(',
')',
'*',
'+',
',',
'-',
'.',
'/',
':',
';',
'<',
'=',
'>',
'?',
'@',
'[',
'\\',
']',
'^',
'_',
'`',
'{',
'|',
'}',
'~',
];
// Electron detection (kept for reference; renderer-process check).
export const IMAGE_EXT_REG = /\.(jpeg|jpg|png|gif|svg|webp)(?=\?|$)/i;
export const isFirefox
= typeof navigator !== 'undefined' && navigator.userAgent.includes('Firefox');
export const isOsx
= typeof window !== 'undefined'
&& window.navigator
&& /Mac/.test(window.navigator.userAgent);
export const isWin
= typeof window !== 'undefined'
&& window.navigator
&& /win32|wow32|win64|wow64/i.test(window.navigator.userAgent);
// http[s] (domain or IPv4 or localhost or IPv6) [port] /not-white-space
export const URL_REG
= /^http(s)?:\/\/([\w\-.~]+\.[a-z]{2,}|[0-9.]+|localhost|\[[a-f0-9.:]+\])(:\d{1,5})?\/\S+/i;
export const PREVIEW_DOMPURIFY_CONFIG = {
// do not forbid `class` because `code` element use class to present language
FORBID_ATTR: ['style', 'contenteditable'],
ALLOW_DATA_ATTR: false,
USE_PROFILES: {
html: true,
svg: true,
svgFilters: true,
mathMl: false,
},
RETURN_TRUSTED_TYPE: false,
};
export const EXPORT_DOMPURIFY_CONFIG = {
FORBID_ATTR: ['contenteditable'],
ALLOW_DATA_ATTR: false,
ADD_ATTR: ['data-align'],
USE_PROFILES: {
html: true,
svg: true,
svgFilters: true,
mathMl: false,
},
RETURN_TRUSTED_TYPE: false,
// Allow "file" protocol to export images on Windows (#1997).
ALLOWED_URI_REGEXP:
/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp|file):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i,
};
export const DEFAULT_SEARCH_OPTIONS = {
isCaseSensitive: false,
isWholeWord: false,
isRegexp: false,
selectHighlight: false,
highlightIndex: -1,
};
export const LINE_BREAK = '\n';
export const DEFAULT_TURNDOWN_CONFIG = {
headingStyle: 'atx', // setext or atx
hr: '---',
bulletListMarker: '-', // -, +, or *
codeBlockStyle: 'fenced', // fenced or indented
fence: '```', // ``` or ~~~
emDelimiter: '*', // _ or *
strongDelimiter: '**', // ** or __
linkStyle: 'inlined',
linkReferenceStyle: 'full',
blankReplacement(
_content: unknown,
// Turndown passes its internal node object: a real DOM Element
// plus the augmented `isBlock` flag the library adds when walking.
node: Element & { isBlock?: boolean },
_options: unknown,
) {
if (node && node.classList.contains('mu-soft-line-break'))
return LINE_BREAK;
else if (node && node.classList.contains('mu-hard-line-break'))
return ` ${LINE_BREAK}`;
else if (node && node.classList.contains('mu-hard-line-break-space'))
return '';
else
return node.isBlock ? '\n\n' : '';
},
};