index.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. <template>
  2. <view class="wd-markdown" :style="'font-size: ' + fontSize + 'rpx;'">
  3. <rich-text :nodes="_html_var" />
  4. </view>
  5. </template>
  6. <script>
  7. import MarkdownIt from './utils/markdown-it.min.js';
  8. import highlight from './utils/highlight.min.js';
  9. import hljsJs from './utils/hljs_javascript.min.js';
  10. import hljsCss from './utils/hljs_css.min.js';
  11. import { addCustomClassPlugin } from './utils/plugin';
  12. export default {
  13. data() {
  14. return {
  15. _html_var: '',
  16. mdInstance: null
  17. };
  18. },
  19. options: {
  20. virtualHost: true
  21. },
  22. props: {
  23. className: {
  24. type: String,
  25. default: ''
  26. },
  27. style: {
  28. type: String,
  29. default: ''
  30. },
  31. id: {
  32. type: String,
  33. default: ''
  34. },
  35. markdown: {
  36. type: String,
  37. default: ''
  38. },
  39. fontSize: {
  40. type: Number,
  41. default: 32
  42. },
  43. options: {
  44. type: Object,
  45. default: () => ({})
  46. }
  47. },
  48. methods: {
  49. attached() {
  50. this.init();
  51. this.updateWidgetAPI();
  52. },
  53. init() {
  54. const { options } = this;
  55. const hljs = highlight();
  56. const javascript = hljsJs();
  57. const css = hljsCss();
  58. hljs.registerLanguage('javascript', javascript);
  59. hljs.registerLanguage('css', css);
  60. const md = new MarkdownIt({
  61. // 默认开启高亮
  62. highlight: function (str, lang) {
  63. if (lang && hljs.getLanguage(lang)) {
  64. try {
  65. return (
  66. '<pre class="_pre"><code class="hljs">' +
  67. hljs.highlight(str, {
  68. language: lang,
  69. ignoreIllegals: true
  70. }).value +
  71. '</code></pre>'
  72. );
  73. } catch (__) {
  74. console.log('CatchClause', __);
  75. console.log('CatchClause', __);
  76. }
  77. }
  78. return '<pre class="_pre"><code class="hljs">' + str + '</code></pre>';
  79. },
  80. ...options
  81. });
  82. // console.log(md.renderer.rules)
  83. addCustomClassPlugin(md);
  84. this.setData({
  85. mdInstance: md
  86. });
  87. this.$emit('onReady', {
  88. detail: {
  89. markdownInstance: md
  90. }
  91. });
  92. this.setData({
  93. _html_var: md.render(this.markdown)
  94. });
  95. },
  96. updateWidgetAPI() {
  97. if (this.setReadonlyAttributes) {
  98. this.setReadonlyAttributes({
  99. value: this.markdown,
  100. markdownInstance: this.mdInstance,
  101. updateMarkdownInstance: ({ markdownInstance }) =>
  102. this.setData({
  103. mdInstance: markdownInstance
  104. })
  105. });
  106. }
  107. }
  108. },
  109. watch: {
  110. markdown: function () {
  111. const { mdInstance } = this;
  112. if (!mdInstance) {
  113. return;
  114. }
  115. const html = mdInstance.render(this.markdown);
  116. // console.log(html)
  117. this.setData({
  118. _html_var: html
  119. });
  120. },
  121. options: function () {
  122. this.init();
  123. },
  124. markdown_mdInstance: {
  125. deep: true,
  126. immediate: true,
  127. handler: function (newValue, oldValue) {
  128. this.updateWidgetAPI();
  129. }
  130. }
  131. },
  132. mounted() {
  133. // 处理小程序 attached 生命周期
  134. this.attached();
  135. },
  136. created: function () {},
  137. computed: {
  138. markdown_mdInstance() {
  139. const { markdown, mdInstance } = this;
  140. return {
  141. markdown,
  142. mdInstance
  143. };
  144. }
  145. }
  146. };
  147. </script>
  148. <style>
  149. /*
  150. markdown 样式
  151. */
  152. .wd-markdown {
  153. word-wrap: break-word;
  154. word-break: normal;
  155. text-align: justify;
  156. }
  157. .wd-markdown ._p {
  158. margin-bottom: 10rpx;
  159. line-height: 1.8;
  160. }
  161. .wd-markdown ._ol {
  162. margin-bottom: 30rpx;
  163. padding-left: 1.2em;
  164. }
  165. .wd-markdown ._ul {
  166. margin-bottom: 30rpx;
  167. padding-left: 1.2em;
  168. }
  169. .wd-markdown ._hr {
  170. border: none;
  171. border-top: 3px solid #eee;
  172. margin-bottom: 10rpx;
  173. }
  174. .wd-markdown ._pre {
  175. max-width: 100%;
  176. padding: 32rpx;
  177. overflow-x: auto;
  178. background-color: rgb(246, 248, 250);
  179. border-radius: 12rpx;
  180. font-family: monospace;
  181. font-size: 1em;
  182. line-height: 1.14285em;
  183. border-radius: 12rpx;
  184. margin-bottom: 10rpx;
  185. }
  186. .wd-markdown ._h1 {
  187. border-bottom-style: double;
  188. border-bottom-width: 6rpx;
  189. font-size: 42rpx;
  190. padding-bottom: 10rpx;
  191. margin-bottom: 20rpx;
  192. }
  193. .wd-markdown ._h2 {
  194. border-bottom-style: solid;
  195. border-bottom-width: 1rpx;
  196. font-size: 40rpx;
  197. padding-bottom: 8rpx;
  198. margin-bottom: 18rpx;
  199. }
  200. .wd-markdown ._h3 {
  201. font-size: 38rpx;
  202. padding-bottom: 6rpx;
  203. margin-bottom: 12rpx;
  204. }
  205. .wd-markdown ._h4 {
  206. font-size: 36rpx;
  207. padding-bottom: 4rpx;
  208. margin-bottom: 12rpx;
  209. }
  210. .wd-markdown ._h5 {
  211. font-size: 34rpx;
  212. padding-bottom: 2rpx;
  213. margin-bottom: 12rpx;
  214. }
  215. .wd-markdown ._h6 {
  216. margin-bottom: 12rpx;
  217. }
  218. .wd-markdown ._a {
  219. margin: 0 8rpx;
  220. border-bottom-width: 1rpx;
  221. border-bottom-style: solid;
  222. line-height: 1;
  223. color: #0000ee;
  224. }
  225. .wd-markdown ._blockquote {
  226. margin: 0 0 10px;
  227. padding: 15px 20px;
  228. background-color: #f1f2f3;
  229. border-left: 5px solid #ccc;
  230. color: #666;
  231. font-style: italic;
  232. }
  233. .wd-markdown ._tableParent {
  234. width: 100%;
  235. overflow-x: auto;
  236. }
  237. .wd-markdown ._table {
  238. min-width: fit-content;
  239. border-collapse: collapse;
  240. margin: 0;
  241. overflow: hidden;
  242. }
  243. .wd-markdown ._table ._th,
  244. .wd-markdown ._table ._td {
  245. box-sizing: border-box;
  246. position: relative;
  247. min-width: 70px;
  248. padding: 0px 5px;
  249. border: 1px solid #e1e6f0;
  250. vertical-align: top;
  251. background-clip: padding-box;
  252. }
  253. .wd-markdown ._table ._th {
  254. font-weight: bold;
  255. background-color: #f5f7fa;
  256. }
  257. .wd-markdown ._table ._td {
  258. background-color: white;
  259. }
  260. .wd-markdown ._table ._th > ._p,
  261. .wd-markdown ._table ._td > ._p {
  262. min-height: 1em;
  263. }
  264. /*!
  265. Theme: GitHub
  266. Description: Light theme as seen on github.com
  267. Author: github.com
  268. Maintainer: @Hirse
  269. Updated: 2021-05-15
  270. Outdated base version: https://github.com/primer/github-syntax-light
  271. Current colors taken from GitHub's CSS
  272. */
  273. .hljs {
  274. color: #24292e;
  275. /* background: #ffffff; */
  276. }
  277. .hljs-doctag,
  278. .hljs-keyword,
  279. .hljs-meta .hljs-keyword,
  280. .hljs-template-tag,
  281. .hljs-template-variable,
  282. .hljs-type,
  283. .hljs-variable.language_ {
  284. /* prettylights-syntax-keyword */
  285. color: #d73a49;
  286. }
  287. .hljs-title,
  288. .hljs-title.class_,
  289. .hljs-title.class_.inherited__,
  290. .hljs-title.function_ {
  291. /* prettylights-syntax-entity */
  292. color: #6f42c1;
  293. }
  294. .hljs-attr,
  295. .hljs-attribute,
  296. .hljs-literal,
  297. .hljs-meta,
  298. .hljs-number,
  299. .hljs-operator,
  300. .hljs-variable,
  301. .hljs-selector-attr,
  302. .hljs-selector-class,
  303. .hljs-selector-id {
  304. /* prettylights-syntax-constant */
  305. color: #005cc5;
  306. }
  307. .hljs-regexp,
  308. .hljs-string,
  309. .hljs-meta .hljs-string {
  310. /* prettylights-syntax-string */
  311. color: #032f62;
  312. }
  313. .hljs-built_in,
  314. .hljs-symbol {
  315. /* prettylights-syntax-variable */
  316. color: #e36209;
  317. }
  318. .hljs-comment,
  319. .hljs-code,
  320. .hljs-formula {
  321. /* prettylights-syntax-comment */
  322. color: #6a737d;
  323. }
  324. .hljs-name,
  325. .hljs-quote,
  326. .hljs-selector-tag,
  327. .hljs-selector-pseudo {
  328. /* prettylights-syntax-entity-tag */
  329. color: #22863a;
  330. }
  331. .hljs-subst {
  332. /* prettylights-syntax-storage-modifier-import */
  333. color: #24292e;
  334. }
  335. .hljs-section {
  336. /* prettylights-syntax-markup-heading */
  337. color: #005cc5;
  338. font-weight: bold;
  339. }
  340. .hljs-bullet {
  341. /* prettylights-syntax-markup-list */
  342. color: #735c0f;
  343. }
  344. .hljs-emphasis {
  345. /* prettylights-syntax-markup-italic */
  346. color: #24292e;
  347. font-style: italic;
  348. }
  349. .hljs-strong {
  350. /* prettylights-syntax-markup-bold */
  351. color: #24292e;
  352. font-weight: bold;
  353. }
  354. .hljs-addition {
  355. /* prettylights-syntax-markup-inserted */
  356. color: #22863a;
  357. background-color: #f0fff4;
  358. }
  359. .hljs-deletion {
  360. /* prettylights-syntax-markup-deleted */
  361. color: #b31d28;
  362. background-color: #ffeef0;
  363. }
  364. .hljs-char.escape_,
  365. .hljs-link,
  366. .hljs-params,
  367. .hljs-property,
  368. .hljs-punctuation,
  369. .hljs-tag {
  370. /* purposely ignored */
  371. }
  372. </style>