diff --git a/src/assets/default-content.md b/src/assets/default-content.md index 8755a04..04c2760 100644 --- a/src/assets/default-content.md +++ b/src/assets/default-content.md @@ -2,30 +2,57 @@ 关于本工具的介绍请看[这篇公众号文章](https://mp.weixin.qq.com/s/pn0LzyfgUj6rGUfVHUksjg)。 - ## 一级标题 这是一级标题 +### 二级标题 1 + +上面是二级标题 + +### 二级标题 2 + +上面是二级标题 + +#### 三级标题 + +上面是三级标题 + +### 二级标题 2 + +上面是二级标题 + +#### 三级标题 + +上面是三级标题 +##### 三级标题 + +上面是三级标题 + +## 一级标题 + +这是一级标题 ### 二级标题 上面是二级标题 +#### 三级标题 + +上面是三级标题 + ## 文字样式 ### 基本样式 你好,我是一个来自地球的人。 -我是一个[智人](https://zh.wikipedia.org/wiki/智人 "学名:Homo sapiens,意为“有智慧的人”"), -我喜欢穿新衣服,都是**黑衣服**。 +我是一个[智人](https://zh.wikipedia.org/wiki/智人 '学名:Homo sapiens,意为“有智慧的人”'),我喜欢穿新衣服,都是**黑衣服**。 我最大的*爱好*是拆汽车,我拆了很多汽车,宝马、奔驰、劳斯莱斯和特斯拉,但是都没装回去。 上面表现了链接和加重两种样式,公众号以外的链接会被转换为脚注。 - ### 注音符号 [注音符号 W3C 定义](http://www.w3.org/TR/ruby/)。支持日语注音假名,小夜時雨【さ・よ・しぐれ】 和 汉语拼音 上海【Shàng・hǎi】 @@ -52,10 +79,9 @@ 食べる{たべる}\n\n english【英文】 will not translated{fan yi}' - ## 段落、列表、引用 -[Markdown](https://sspai.com/post/25137 "认识与入门 Markdown") 是一种写文章用的语法。 +[Markdown](https://sspai.com/post/25137 '认识与入门 Markdown') 是一种写文章用的语法。 我们日常写文章用的工具,比如说 Word,提供了大量排版格式样式相关的选项。 @@ -87,13 +113,10 @@ 代码块,使用微信官方的高亮配色,在代码块标示语言即可。粘贴到公众号后,需要用鼠标点一下代码块,完成高亮。 - ```cpp 你的代码 ``` - - ```cpp #include @@ -125,8 +148,7 @@ int main() { 接下来是表格示例: | Header 1 | Header 2 | -| --- | --- | -| Key 1 | Value 1 | -| Key 2 | Value 2 | -| Key 3 | Value 3 | - +| -------- | -------- | +| Key 1 | Value 1 | +| Key 2 | Value 2 | +| Key 3 | Value 3 | diff --git a/src/assets/scripts/editor.js b/src/assets/scripts/editor.js index e4c313c..c8c8b33 100644 --- a/src/assets/scripts/editor.js +++ b/src/assets/scripts/editor.js @@ -1,124 +1,120 @@ var app = new Vue({ el: '#app', - data: function () { + data: function() { return { title: 'WeChat Format', aboutOutput: '', output: '', source: '', - editorThemes: [ - { label: 'base16-light', value: 'base16-light' }, - { label: 'duotone-light', value: 'duotone-light' }, - { label: 'monokai', value: 'monokai' } - ], + editorThemes: [{ label: 'base16-light', value: 'base16-light' }, { label: 'duotone-light', value: 'duotone-light' }, { label: 'monokai', value: 'monokai' }], currentEditorTheme: 'base16-light', editor: null, - builtinFonts: [ - { label: '衬线', value: "Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif"}, - { label: '无衬线', value: "Roboto, Oxygen, Ubuntu, Cantarell, PingFangSC-light, PingFangTC-light, 'Open Sans', 'Helvetica Neue', sans-serif"} - ], + builtinFonts: [{ label: '衬线', value: "Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif" }, { label: '无衬线', value: "Roboto, Oxygen, Ubuntu, Cantarell, PingFangSC-light, PingFangTC-light, 'Open Sans', 'Helvetica Neue', sans-serif" }], currentFont: "Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif", currentSize: '16px', - sizeOption: [ - { label: '16px', value: '16px', desc: '默认' }, - { label: '17px', value: '17px', desc: '正常' }, - { label: '18px', value: '18px', desc: '稍大' } - ], + sizeOption: [{ label: '16px', value: '16px', desc: '默认' }, { label: '17px', value: '17px', desc: '正常' }, { label: '18px', value: '18px', desc: '稍大' }], currentTheme: 'default', - themeOption: [ - { label: 'default', value: 'default', author: 'Lyric'}, - { label: 'lupeng', value: 'lupeng', author: '鲁鹏'} - ], + themeOption: [{ label: 'default', value: 'default', author: 'Lyric' }, { label: 'lupeng', value: 'lupeng', author: '鲁鹏' }], styleThemes: { default: defaultTheme, lupeng: lupengTheme }, - aboutDialogVisible: false - } + aboutDialogVisible: false, + enableTitleNum: false + }; }, - mounted () { - var self = this + mounted() { + var self = this; this.editor = CodeMirror.fromTextArea(document.getElementById('editor'), { lineNumbers: false, lineWrapping: true, styleActiveLine: true, theme: this.currentEditorTheme, - mode: 'text/x-markdown', + mode: 'text/x-markdown' + }); + this.editor.on('change', function(cm, change) { + self.refresh(); }); - this.editor.on("change", function(cm, change) { - self.refresh() - }) // this.currentFont = this.builtinFonts[0], this.wxRenderer = new WxRenderer({ theme: this.styleThemes.default, fonts: this.currentFont, size: this.currentSize - }) + }); axios({ method: 'get', - url: './assets/default-content.md', - }).then(function (resp) { - self.editor.setValue(resp.data) - }) + url: './assets/default-content.md' + }).then(function(resp) { + self.editor.setValue(resp.data); + }); }, methods: { - renderWeChat: function (source) { - var output = marked(source, { renderer: this.wxRenderer.getRenderer() }) + renderWeChat: function(source) { + var output = marked(source, { renderer: this.wxRenderer.getRenderer() }); if (this.wxRenderer.hasFootnotes()) { - output += this.wxRenderer.buildFootnotes() + output += this.wxRenderer.buildFootnotes(); } - return output + return output; }, - editorThemeChanged: function (editorTheme) { - this.editor.setOption('theme', editorTheme) + editorThemeChanged: function(editorTheme) { + this.editor.setOption('theme', editorTheme); }, - fontChanged: function (fonts) { + fontChanged: function(fonts) { this.wxRenderer.setOptions({ fonts: fonts - }) - this.refresh() + }); + this.refresh(); }, - sizeChanged: function(size){ + sizeChanged: function(size) { this.wxRenderer.setOptions({ size: size - }) - this.refresh() + }); + this.refresh(); }, - themeChanged: function(themeName){ + themeChanged: function(themeName) { var themeName = themeName; var themeObject = this.styleThemes[themeName]; this.wxRenderer.setOptions({ theme: themeObject - }) - this.refresh() + }); + this.refresh(); + }, + titleNumChanged: function(val) { + this.wxRenderer.setOptions({ + enabletitleNum: val + }); + this.refresh(); }, - refresh: function () { - this.output = this.renderWeChat(this.editor.getValue()) + refresh: function() { + this.output = this.renderWeChat(this.editor.getValue()); }, - copy: function () { - var clipboardDiv = document.getElementById('output') + copy: function() { + var clipboardDiv = document.getElementById('output'); clipboardDiv.focus(); - window.getSelection().removeAllRanges(); - var range = document.createRange(); + window.getSelection().removeAllRanges(); + var range = document.createRange(); range.setStartBefore(clipboardDiv.firstChild); range.setEndAfter(clipboardDiv.lastChild); - window.getSelection().addRange(range); + window.getSelection().addRange(range); try { if (document.execCommand('copy')) { this.$message({ - message: '已复制到剪贴板', type: 'success' - }) + message: '已复制到剪贴板', + type: 'success' + }); } else { this.$message({ - message: '未能复制到剪贴板,请全选后右键复制', type: 'warning' - }) + message: '未能复制到剪贴板,请全选后右键复制', + type: 'warning' + }); } } catch (err) { this.$message({ - message: '未能复制到剪贴板,请全选后右键复制', type: 'warning' - }) + message: '未能复制到剪贴板,请全选后右键复制', + type: 'warning' + }); } } } -}) \ No newline at end of file +}); diff --git a/src/assets/scripts/renderers/wx-renderer.js b/src/assets/scripts/renderers/wx-renderer.js index 135c7c0..866d0d5 100644 --- a/src/assets/scripts/renderers/wx-renderer.js +++ b/src/assets/scripts/renderers/wx-renderer.js @@ -1,126 +1,157 @@ -var WxRenderer = function (opts) { - this.opts = opts - var ENV_USE_REFERENCES = true - var ENV_STETCH_IMAGE = true +var WxRenderer = function(opts) { + this.opts = opts; + var ENV_USE_REFERENCES = true; + var ENV_STETCH_IMAGE = true; - var footnotes = [] - var footnoteindex = 0 - var styleMapping = null + var footnotes = []; + var footnoteindex = 0; + var styleMapping = null; - var FONT_FAMILY_MONO = "Operator Mono, Consolas, Monaco, Menlo, monospace" + var FONT_FAMILY_MONO = 'Operator Mono, Consolas, Monaco, Menlo, monospace'; - var COPY = function (base, extend) { return Object.assign({}, base, extend)} + var COPY = function(base, extend) { + return Object.assign({}, base, extend); + }; - this.buildTheme = function (themeTpl) { - var mapping = {} + var Level = { + h2: 0, + h3: 0, + h4: 0, + h5: 0, + currLev: 0, + lastLev: 0, + toString: function() { + var str = `${this.h2}.${this.h3}.${this.h4}.${this.h5}`; + var s = str.replace(/(\.0)*$/g, ''); + return s == '0' ? '' : s; + }, + setCurrLev: function(lev) { + this.lastLev = this.currLev; + this.currLev = lev; + if (this.lastLev > this.currLev) { + this.reset(lev); + } + this['h' + lev]++; + }, + reset: function(lev = 1) { + lev++; + while (lev <= 5) { + this['h' + lev] = 0; + lev++; + } + } + }; + this.buildTheme = function(themeTpl) { + var mapping = {}; var base = COPY(themeTpl.BASE, { 'font-family': this.opts.fonts, 'font-size': this.opts.size - }) + }); var base_block = COPY(base, { - 'margin': '20px 10px' - }) + margin: '20px 10px' + }); for (var ele in themeTpl.inline) { if (themeTpl.inline.hasOwnProperty(ele)) { - var style = themeTpl.inline[ele] + var style = themeTpl.inline[ele]; if (ele === 'codespan') { - style['font-family'] = FONT_FAMILY_MONO + style['font-family'] = FONT_FAMILY_MONO; } - mapping[ele] = COPY(base, style) + mapping[ele] = COPY(base, style); } } for (var ele in themeTpl.block) { if (themeTpl.block.hasOwnProperty(ele)) { - var style = themeTpl.block[ele] + var style = themeTpl.block[ele]; if (ele === 'code') { - style['font-family'] = FONT_FAMILY_MONO + style['font-family'] = FONT_FAMILY_MONO; } - mapping[ele] = COPY(base_block, style) + mapping[ele] = COPY(base_block, style); } } - return mapping - } + return mapping; + }; - var S = function (tokenName) { - var arr = [] - var dict = styleMapping[tokenName] + var S = function(tokenName) { + var arr = []; + var dict = styleMapping[tokenName]; for (const key in dict) { - arr.push(key + ':' + dict[key]) + arr.push(key + ':' + dict[key]); } - return 'style="' + arr.join(';') + '"' - } + return 'style="' + arr.join(';') + '"'; + }; - var addFootnote = function (title, link) { - footnoteindex += 1 - footnotes.push([footnoteindex, title, link]) - return footnoteindex - } + var addFootnote = function(title, link) { + footnoteindex += 1; + footnotes.push([footnoteindex, title, link]); + return footnoteindex; + }; - this.buildFootnotes = function () { - var footnoteArray = footnotes.map(function (x) { + this.buildFootnotes = function() { + var footnoteArray = footnotes.map(function(x) { if (x[1] === x[2]) { - return '[' + x[0] + ']: ' + x[1] +'
' + return '[' + x[0] + ']: ' + x[1] + '
'; } - return '[' + x[0] + '] ' + x[1] + ': ' + x[2] +'
' - }) - return '

References

' + footnoteArray.join('\n') + '

' - } + return '[' + x[0] + '] ' + x[1] + ': ' + x[2] + '
'; + }); + return '

References

' + footnoteArray.join('\n') + '

'; + }; - this.setOptions = function (newOpts) { - this.opts = COPY(this.opts, newOpts) - } + this.setOptions = function(newOpts) { + this.opts = COPY(this.opts, newOpts); + }; - this.hasFootnotes = function () { - return footnotes.length !== 0 - } + this.hasFootnotes = function() { + return footnotes.length !== 0; + }; - this.getRenderer = function () { - footnotes = [] - footnoteindex = 0 - - styleMapping = this.buildTheme(this.opts.theme) - var renderer = new marked.Renderer() + this.getRenderer = function() { + footnotes = []; + footnoteindex = 0; + Level.reset(); + styleMapping = this.buildTheme(this.opts.theme); + var renderer = new marked.Renderer(); FuriganaMD.register(renderer); - - renderer.heading = function (text, level) { + var self = this; + renderer.heading = function(text, level) { + console.info(text, level); + if (self.opts.enabletitleNum) { + Level.setCurrLev(level); + } + if (level < 3) { - return '

' + text + '

' + return '

' + Level + text + '

'; } else { - return '

' + text + '

' + return '

' + Level + text + '

'; } - } - renderer.paragraph = function (text) { - return '

' + text + '

' - } - renderer.blockquote = function (text) { - return '
' + text + '
' - } - renderer.code = function (text, infostring) { - text = text.replace(//g, ">") - - var lines = text.split('\n') - var codeLines = [] - var numbers = [] + }; + renderer.paragraph = function(text) { + return '

' + text + '

'; + }; + renderer.blockquote = function(text) { + return '
' + text + '
'; + }; + renderer.code = function(text, infostring) { + text = text.replace(//g, '>'); + + var lines = text.split('\n'); + var codeLines = []; + var numbers = []; for (let i = 0; i < lines.length; i++) { - const line = lines[i] - codeLines.push('' + (line || '
') + '
') - numbers.push('
  • ') + const line = lines[i]; + codeLines.push('' + (line || '
    ') + '
    '); + numbers.push('
  • '); } - var lang = infostring || '' - return '
    ' - + '' - + '
    ' 
    -          + codeLines.join('')
    -        + '
    ' - } - renderer.codespan = function (text, infostring) { - return '' + text + '' - } - renderer.listitem = function (text) { + var lang = infostring || ''; + return '
    ' + '' + '
    ' + codeLines.join('') + '
    '; + }; + renderer.codespan = function(text, infostring) { + return '' + text + ''; + }; + renderer.listitem = function(text) { return '<%s/>' + text + ''; - } - renderer.list = function (text, ordered, start) { + }; + renderer.list = function(text, ordered, start) { var segments = text.split('<%s/>'); if (!ordered) { text = segments.join('•'); @@ -131,36 +162,36 @@ var WxRenderer = function (opts) { text = text + i + '.' + segments[i]; } return '

    ' + text + '

    '; - } - renderer.image = function (href, title, text) { - return ''+text+'' - } - renderer.link = function (href, title, text) { + }; + renderer.image = function(href, title, text) { + return '' + text + ''; + }; + renderer.link = function(href, title, text) { if (href.indexOf('https://mp.weixin.qq.com') === 0) { - return '' + text + ''; - }else if( href === text){ + return '' + text + ''; + } else if (href === text) { return text; } else { if (ENV_USE_REFERENCES) { - var ref = addFootnote(title || text, href) - return '' + text + '['+ref+']'; + var ref = addFootnote(title || text, href); + return '' + text + '[' + ref + ']'; } else { - return '' + text + ''; + return '' + text + ''; } } - } - renderer.strong = renderer.em = function (text) { - return '' + text + ''; - } - renderer.table = function (header, body) { - return '' + header + '' + body + '
    '; - } - renderer.tablecell = function (text, flags) { - return '' + text + ''; - } - renderer.hr = function(){ + }; + renderer.strong = renderer.em = function(text) { + return '' + text + ''; + }; + renderer.table = function(header, body) { + return '' + header + '' + body + '
    '; + }; + renderer.tablecell = function(text, flags) { + return '' + text + ''; + }; + renderer.hr = function() { return '
    '; - } - return renderer - } -} \ No newline at end of file + }; + return renderer; + }; +}; diff --git a/src/index.html b/src/index.html index b68eb27..5832d59 100644 --- a/src/index.html +++ b/src/index.html @@ -1,130 +1,121 @@ - - - - - - 微信公众号格式化编辑器 - - - - - - - - - - - -
    - - - - - - - - - - - - - - {{ font.label }} - Abc - - - - - - - {{ size.label }} - {{ size.desc }} - - - - - - - {{ theme.label }} - {{ theme.author }} - - - - - 关于 - - - - - - - -
    -
    全选复制或点此复制,然后在公众号编辑器粘贴
    -
    -
    + + + + + + 微信公众号格式化编辑器 + + + + + + + + + + + +
    + + + + + + + + + + + + + {{ font.label }} + Abc + + + + + + + {{ size.label }} + {{ size.desc }} + + + + + + + {{ theme.label }} + {{ theme.author }} + + + + + + + + 关于 + + + + + + + +
    +
    全选复制或点此复制,然后在公众号编辑器粘贴
    +
    +
    -
    -
    -
    -
    -
    -
    + + + + + - -
    -

    WeChat Format 有什么用?

    -

    能较好地排版;

    -

    能解决 ulol 渲染时样式被微信编辑器重置的问题;

    -

    能把外部链接自动转为参考文献索引,并且附在文章末尾

    -

     

    -

    关于我

    -

    我是 Lyric。如果你喜欢我的工具,可以:

    -

    关注我的公众号 "iamlyricw",博客Github

    -

    - 微信打赏我: - -

    -
    - - 打赏了! - -
    -
    + +
    +

    WeChat Format 有什么用?

    +

    能较好地排版;

    +

    能解决 ulol 渲染时样式被微信编辑器重置的问题;

    +

    能把外部链接自动转为参考文献索引,并且附在文章末尾

    +

     

    +

    关于我

    +

    我是 Lyric。如果你喜欢我的工具,可以:

    +

    关注我的公众号 "iamlyricw",博客Github

    +

    + 微信打赏我: + +

    +
    + + 打赏了! + +
    + - - - - - - - - + + + + + - - - - - - - - - \ No newline at end of file + + + + + + + + + + + +