Options.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. import insertAfterSVG from "../../assets/icons/after.svg";
  2. import outlinerSVG from "../../assets/icons/align-center.svg";
  3. import insertBeforeSVG from "../../assets/icons/before.svg";
  4. import boldSVG from "../../assets/icons/bold.svg";
  5. import bothSVG from "../../assets/icons/both.svg";
  6. import bugSVG from "../../assets/icons/bug.svg";
  7. import checkSVG from "../../assets/icons/check.svg";
  8. import codeThemeSVG from "../../assets/icons/code-theme.svg";
  9. import codeSVG from "../../assets/icons/code.svg";
  10. import editSVG from "../../assets/icons/edit.svg";
  11. import emojiSVG from "../../assets/icons/emoji.svg";
  12. import fullscreenSVG from "../../assets/icons/fullscreen.svg";
  13. import headingsSVG from "../../assets/icons/headings.svg";
  14. import helpSVG from "../../assets/icons/help.svg";
  15. import indentSVG from "../../assets/icons/indent.svg";
  16. import infoSVG from "../../assets/icons/info.svg";
  17. import inlineCodeSVG from "../../assets/icons/inline-code.svg";
  18. import italicSVG from "../../assets/icons/italic.svg";
  19. import lineSVG from "../../assets/icons/line.svg";
  20. import linkSVG from "../../assets/icons/link.svg";
  21. import listSVG from "../../assets/icons/list.svg";
  22. import moreSVG from "../../assets/icons/more.svg";
  23. import orderedListVG from "../../assets/icons/ordered-list.svg";
  24. import formatSVG from "../../assets/icons/outdent.svg";
  25. import outdentSVG from "../../assets/icons/outdent.svg";
  26. import previewSVG from "../../assets/icons/preview.svg";
  27. import quoteSVG from "../../assets/icons/quote.svg";
  28. import recordSVG from "../../assets/icons/record.svg";
  29. import redoSVG from "../../assets/icons/redo.svg";
  30. import strikekSVG from "../../assets/icons/strike.svg";
  31. import tableSVG from "../../assets/icons/table.svg";
  32. import contentThemeSVG from "../../assets/icons/theme.svg";
  33. import undoSVG from "../../assets/icons/undo.svg";
  34. import uploadSVG from "../../assets/icons/upload.svg";
  35. import {VDITOR_VERSION} from "../constants";
  36. export class Options {
  37. public options: IOptions;
  38. private defaultOptions: IOptions = {
  39. after: undefined,
  40. cache: {
  41. enable: true,
  42. },
  43. cdn: `https://cdn.jsdelivr.net/npm/vditor@${VDITOR_VERSION}`,
  44. classes: {
  45. preview: "",
  46. },
  47. counter: {
  48. enable: false,
  49. type: "markdown",
  50. },
  51. debugger: false,
  52. height: "auto",
  53. hint: {
  54. delay: 200,
  55. emoji: {
  56. "+1": "👍",
  57. "-1": "👎",
  58. "confused": "😕",
  59. "eyes": "👀️",
  60. "heart": "❤️",
  61. "rocket": "🚀️",
  62. "smile": "😄",
  63. "tada": "🎉️",
  64. },
  65. emojiPath: `https://cdn.jsdelivr.net/npm/vditor@${VDITOR_VERSION}/dist/images/emoji`,
  66. },
  67. keymap: {
  68. deleteLine: "⌘-Backspace",
  69. duplicate: "⌘-D",
  70. },
  71. lang: "zh_CN",
  72. mode: "wysiwyg",
  73. placeholder: "",
  74. preview: {
  75. delay: 1000,
  76. hljs: {
  77. enable: true,
  78. lineNumber: false,
  79. style: "github",
  80. },
  81. markdown: {
  82. autoSpace: false,
  83. chinesePunct: false,
  84. codeBlockPreview: true,
  85. fixTermTypo: false,
  86. footnotes: true,
  87. setext: true,
  88. theme: "light",
  89. toc: false,
  90. },
  91. math: {
  92. engine: "KaTeX",
  93. inlineDigit: false,
  94. macros: {},
  95. },
  96. maxWidth: 800,
  97. mode: "both",
  98. },
  99. resize: {
  100. enable: false,
  101. position: "bottom",
  102. },
  103. theme: "classic",
  104. toolbar: [
  105. "emoji",
  106. "headings",
  107. "bold",
  108. "italic",
  109. "strike",
  110. "link",
  111. "|",
  112. "list",
  113. "ordered-list",
  114. "check",
  115. "outdent",
  116. "indent",
  117. "|",
  118. "quote",
  119. "line",
  120. "code",
  121. "inline-code",
  122. "insert-before",
  123. "insert-after",
  124. "|",
  125. "upload",
  126. "record",
  127. "table",
  128. "|",
  129. "undo",
  130. "redo",
  131. "|",
  132. {
  133. name: "more",
  134. toolbar: [
  135. "fullscreen",
  136. "edit-mode",
  137. "both",
  138. "format",
  139. "preview",
  140. "outline",
  141. "content-theme",
  142. "code-theme",
  143. "devtools",
  144. "info",
  145. "help",
  146. ],
  147. }],
  148. toolbarConfig: {
  149. hide: false,
  150. pin: false,
  151. },
  152. typewriterMode: false,
  153. upload: {
  154. filename: (name: string) => name.replace(/\W/g, ""),
  155. linkToImgUrl: "",
  156. max: 10 * 1024 * 1024,
  157. url: "",
  158. withCredentials: false,
  159. },
  160. value: "",
  161. width: "auto",
  162. };
  163. private toolbarItem = [{
  164. hotkey: "⌘-E",
  165. icon: emojiSVG,
  166. name: "emoji",
  167. tipPosition: "ne",
  168. }, {
  169. hotkey: "⌘-H",
  170. icon: headingsSVG,
  171. name: "headings",
  172. tipPosition: "ne",
  173. }, {
  174. hotkey: "⌘-B",
  175. icon: boldSVG,
  176. name: "bold",
  177. prefix: "**",
  178. suffix: "**",
  179. tipPosition: "ne",
  180. }, {
  181. hotkey: "⌘-I",
  182. icon: italicSVG,
  183. name: "italic",
  184. prefix: "*",
  185. suffix: "*",
  186. tipPosition: "ne",
  187. }, {
  188. hotkey: "⌘-S",
  189. icon: strikekSVG,
  190. name: "strike",
  191. prefix: "~~",
  192. suffix: "~~",
  193. tipPosition: "ne",
  194. }, {
  195. hotkey: "⌘-K",
  196. icon: linkSVG,
  197. name: "link",
  198. prefix: "[",
  199. suffix: "](https://)",
  200. tipPosition: "n",
  201. }, {
  202. name: "|",
  203. }, {
  204. hotkey: "⌘-L",
  205. icon: listSVG,
  206. name: "list",
  207. prefix: "* ",
  208. tipPosition: "n",
  209. }, {
  210. hotkey: "⌘-O",
  211. icon: orderedListVG,
  212. name: "ordered-list",
  213. prefix: "1. ",
  214. tipPosition: "n",
  215. }, {
  216. hotkey: "⌘-J",
  217. icon: checkSVG,
  218. name: "check",
  219. prefix: "* [ ] ",
  220. tipPosition: "n",
  221. }, {
  222. hotkey: "⌘-⇧-I",
  223. icon: outdentSVG,
  224. name: "outdent",
  225. tipPosition: "n",
  226. }, {
  227. hotkey: "⌘-⇧-O",
  228. icon: indentSVG,
  229. name: "indent",
  230. tipPosition: "n",
  231. }, {
  232. name: "|",
  233. }, {
  234. hotkey: "⌘-;",
  235. icon: quoteSVG,
  236. name: "quote",
  237. prefix: "> ",
  238. tipPosition: "n",
  239. }, {
  240. hotkey: "⌘-⇧-H",
  241. icon: lineSVG,
  242. name: "line",
  243. prefix: "---",
  244. tipPosition: "n",
  245. }, {
  246. hotkey: "⌘-U",
  247. icon: codeSVG,
  248. name: "code",
  249. prefix: "```\n",
  250. suffix: "\n```",
  251. tipPosition: "n",
  252. }, {
  253. hotkey: "⌘-G",
  254. icon: inlineCodeSVG,
  255. name: "inline-code",
  256. prefix: "`",
  257. suffix: "`",
  258. tipPosition: "n",
  259. }, {
  260. hotkey: "⌘-⇧-B",
  261. icon: insertBeforeSVG,
  262. name: "insert-before",
  263. tipPosition: "n",
  264. }, {
  265. hotkey: "⌘-⇧-E",
  266. icon: insertAfterSVG,
  267. name: "insert-after",
  268. tipPosition: "n",
  269. }, {
  270. name: "|",
  271. }, {
  272. icon: uploadSVG,
  273. name: "upload",
  274. tipPosition: "n",
  275. }, {
  276. icon: recordSVG,
  277. name: "record",
  278. tipPosition: "n",
  279. }, {
  280. hotkey: "⌘-M",
  281. icon: tableSVG,
  282. name: "table",
  283. prefix: "| col1",
  284. suffix: " | col2 | col3 |\n| --- | --- | --- |\n| | | |\n| | | |",
  285. tipPosition: "n",
  286. }, {
  287. name: "|",
  288. }, {
  289. hotkey: "⌘-Z",
  290. icon: undoSVG,
  291. name: "undo",
  292. tipPosition: "nw",
  293. }, {
  294. hotkey: "⌘-Y",
  295. icon: redoSVG,
  296. name: "redo",
  297. tipPosition: "nw",
  298. }, {
  299. name: "|",
  300. }, {
  301. icon: moreSVG,
  302. name: "more",
  303. tipPosition: "e",
  304. }, {
  305. hotkey: "⌘-'",
  306. icon: fullscreenSVG,
  307. name: "fullscreen",
  308. tipPosition: "nw",
  309. }, {
  310. icon: editSVG,
  311. name: "edit-mode",
  312. tipPosition: "nw",
  313. }, {
  314. hotkey: "⌘-P",
  315. icon: bothSVG,
  316. name: "both",
  317. tipPosition: "nw",
  318. }, {
  319. icon: previewSVG,
  320. name: "preview",
  321. tipPosition: "nw",
  322. }, {
  323. hotkey: "⌘-⇧-F",
  324. icon: formatSVG,
  325. name: "format",
  326. tipPosition: "nw",
  327. }, {
  328. icon: outlinerSVG,
  329. name: "outline",
  330. tipPosition: "nw",
  331. }, {
  332. icon: contentThemeSVG,
  333. name: "content-theme",
  334. tipPosition: "nw",
  335. }, {
  336. icon: codeThemeSVG,
  337. name: "code-theme",
  338. tipPosition: "nw",
  339. }, {
  340. icon: bugSVG,
  341. name: "devtools",
  342. tipPosition: "nw",
  343. }, {
  344. icon: infoSVG,
  345. name: "info",
  346. tipPosition: "nw",
  347. }, {
  348. icon: helpSVG,
  349. name: "help",
  350. tipPosition: "nw",
  351. }, {
  352. name: "br",
  353. }];
  354. constructor(options: IOptions) {
  355. this.options = options;
  356. }
  357. public merge(): IOptions {
  358. if (this.options) {
  359. if (this.options.upload) {
  360. this.options.upload = Object.assign({}, this.defaultOptions.upload, this.options.upload);
  361. }
  362. if (this.options.cache) {
  363. this.options.cache = Object.assign({}, this.defaultOptions.cache, this.options.cache);
  364. }
  365. if (this.options.classes) {
  366. this.options.classes = Object.assign({}, this.defaultOptions.classes, this.options.classes);
  367. }
  368. if (this.options.keymap) {
  369. this.options.keymap = Object.assign({}, this.defaultOptions.keymap, this.options.keymap);
  370. }
  371. if (this.options.preview) {
  372. this.options.preview = Object.assign({}, this.defaultOptions.preview, this.options.preview);
  373. if (this.options.preview.hljs) {
  374. this.options.preview.hljs =
  375. Object.assign({}, this.defaultOptions.preview.hljs, this.options.preview.hljs);
  376. }
  377. if (this.options.preview.math) {
  378. this.options.preview.math =
  379. Object.assign({}, this.defaultOptions.preview.math, this.options.preview.math);
  380. }
  381. if (this.options.preview.markdown) {
  382. if (!this.options.preview.markdown.theme && this.options.theme && this.options.theme === "dark") {
  383. this.options.preview.markdown.theme = "dark";
  384. }
  385. this.options.preview.markdown =
  386. Object.assign({}, this.defaultOptions.preview.markdown, this.options.preview.markdown);
  387. }
  388. }
  389. if (this.options.hint) {
  390. this.options.hint = Object.assign({}, this.defaultOptions.hint, this.options.hint);
  391. }
  392. if (this.options.resize) {
  393. this.options.resize = Object.assign({}, this.defaultOptions.resize, this.options.resize);
  394. }
  395. if (this.options.counter) {
  396. this.options.counter = Object.assign({}, this.defaultOptions.counter, this.options.counter);
  397. }
  398. if (this.options.toolbarConfig) {
  399. this.options.toolbarConfig =
  400. Object.assign({}, this.defaultOptions.toolbarConfig, this.options.toolbarConfig);
  401. }
  402. if (this.options.toolbar) {
  403. this.options.toolbar = this.mergeToolbar(this.options.toolbar);
  404. } else {
  405. this.options.toolbar = this.mergeToolbar(this.defaultOptions.toolbar);
  406. }
  407. }
  408. const mergedOptions = Object.assign({}, this.defaultOptions, this.options);
  409. if (mergedOptions.cache.enable && !mergedOptions.cache.id) {
  410. throw new Error("need options.cache.id, see https://hacpai.com/article/1549638745630#options");
  411. }
  412. return mergedOptions;
  413. }
  414. private mergeToolbar(toolbar: Array<string | IMenuItem>) {
  415. const toolbarResult: IMenuItem[] = [];
  416. toolbar.forEach((menuItem: IMenuItem) => {
  417. let currentMenuItem = menuItem;
  418. this.toolbarItem.forEach((defaultMenuItem: IMenuItem) => {
  419. if (typeof menuItem === "string" && defaultMenuItem.name === menuItem) {
  420. currentMenuItem = defaultMenuItem;
  421. }
  422. if (typeof menuItem === "object" && defaultMenuItem.name === menuItem.name) {
  423. currentMenuItem = Object.assign({}, defaultMenuItem, menuItem);
  424. }
  425. });
  426. if (menuItem.toolbar) {
  427. currentMenuItem.toolbar = this.mergeToolbar(menuItem.toolbar);
  428. }
  429. toolbarResult.push(currentMenuItem);
  430. });
  431. return toolbarResult;
  432. }
  433. }