index.vue 8.7 KB

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