diff --git a/README.md b/README.md index 171e671..45eb725 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ npm install markdown-it-vue ## Supports +- Image size and Viewer - Official markdown syntax. - GFM TOC - GFM style @@ -49,6 +50,7 @@ npm install markdown-it-vue internal plugin list: +- markdown-it-image - markdown-it-font-awsome - markdown-it-link-attributes - markdown-it-highlight @@ -106,6 +108,10 @@ amd default plugins options: }, mermaid: { theme: 'default' + }, + image: { + hAlign: 'left', + viewer: true } } ``` @@ -167,6 +173,14 @@ PR for you lang wich you want. - Prolog - Erlang +## image size + +```md +![image size](https://http://www.aqcoder.com/ravenq-qr.png =50x50) +![image size](https://http://www.aqcoder.com/ravenq-qr.png =x50) +![image size](https://http://www.aqcoder.com/ravenq-qr.png =50x) +``` + ## about echarts use echarts.simple to reduce the bundle size. diff --git a/README_CN.md b/README_CN.md index 8bb63a9..69f9c2b 100644 --- a/README_CN.md +++ b/README_CN.md @@ -20,6 +20,7 @@ npm install markdown-it-vue ## 特性 +- 图片大小控制及图片预览 - Official markdown syntax. - GFM TOC - GFM style @@ -54,6 +55,7 @@ npm install markdown-it-vue 内置插件: +- markdown-it-image - markdown-it-font-awsome - markdown-it-link-attributes - markdown-it-highlight @@ -111,6 +113,10 @@ options: { }, mermaid: { theme: 'default' + }, + image: { + hAlign: 'left', + viewer: true } } ``` @@ -176,6 +182,14 @@ this.$refs.myMarkdownItVue.use(MyMarkdownItPlugin) - Prolog - Erlang +## 图片大小控制语法 + +```md +![image size](https://http://www.aqcoder.com/ravenq-qr.png =50x50) +![image size](https://http://www.aqcoder.com/ravenq-qr.png =x50) +![image size](https://http://www.aqcoder.com/ravenq-qr.png =50x) +``` + ## 关于 echarts 为了减少包的大小,只引用 echarts.simple。 diff --git a/example/components/example.js b/example/components/example.js index dcfd530..3407769 100644 --- a/example/components/example.js +++ b/example/components/example.js @@ -1,6 +1,11 @@ export default ` # markdown-it-vue +## Image size and Viewer + +![gvf](http://www.aqcoder.com/gvf-project.png =x50) +![ravenq](http://www.aqcoder.com/ravenq-qr.png =50x50) + ## GitHub Table of Contents [toc] diff --git a/package.json b/package.json index 6238a93..20e0000 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "markdown-it-vue", - "version": "1.1.4", + "version": "1.1.5", "private": false, "description": "The vue lib for markdown-it", "author": { diff --git a/src/fonts/element-icons.ttf b/src/fonts/element-icons.ttf new file mode 100644 index 0000000..91b74de Binary files /dev/null and b/src/fonts/element-icons.ttf differ diff --git a/src/fonts/element-icons.woff b/src/fonts/element-icons.woff new file mode 100644 index 0000000..02b9a25 Binary files /dev/null and b/src/fonts/element-icons.woff differ diff --git a/src/markdown-it-image/image-viewer.vue b/src/markdown-it-image/image-viewer.vue new file mode 100644 index 0000000..31b85c2 --- /dev/null +++ b/src/markdown-it-image/image-viewer.vue @@ -0,0 +1,481 @@ + + + + + diff --git a/src/markdown-it-image/index.js b/src/markdown-it-image/index.js new file mode 100644 index 0000000..daab177 --- /dev/null +++ b/src/markdown-it-image/index.js @@ -0,0 +1,283 @@ +function parseNextNumber(str, pos, max) { + var code, + start = pos, + result = { + ok: false, + pos: pos, + value: '' + } + + code = str.charCodeAt(pos) + + while ( + (pos < max && code >= 0x30 /* 0 */ && code <= 0x39 /* 9 */) || + code === 0x25 /* % */ + ) { + code = str.charCodeAt(++pos) + } + + result.ok = true + result.pos = pos + result.value = str.slice(start, pos) + + return result +} + +function parseImageSize(str, pos, max) { + var code, + result = { + ok: false, + pos: 0, + width: '', + height: '' + } + + if (pos >= max) { + return result + } + + code = str.charCodeAt(pos) + + if (code !== 0x3d /* = */) { + return result + } + + pos++ + + // size must follow = without any white spaces as follows + // (1) =300x200 + // (2) =300x + // (3) =x200 + code = str.charCodeAt(pos) + if (code !== 0x78 /* x */ && (code < 0x30 || code > 0x39) /* [0-9] */) { + return result + } + + // parse width + var resultW = parseNextNumber(str, pos, max) + pos = resultW.pos + + // next charactor must be 'x' + code = str.charCodeAt(pos) + if (code !== 0x78 /* x */) { + return result + } + + pos++ + + // parse height + var resultH = parseNextNumber(str, pos, max) + pos = resultH.pos + + result.width = resultW.value + result.height = resultH.value + result.pos = pos + result.ok = true + return result +} + +export default (md , options) => { + md.inline.ruler.before('emphasis', 'image', (state, silent) => { + var attrs, + code, + content, + label, + labelEnd, + labelStart, + pos, + ref, + res, + title, + token, + tokens, + start, + href = '', + oldPos = state.pos, + max = state.posMax, + width = '', + height = '' + + if (state.src.charCodeAt(state.pos) !== 0x21 /* ! */) { + return false + } + if (state.src.charCodeAt(state.pos + 1) !== 0x5b /* [ */) { + return false + } + + labelStart = state.pos + 2 + labelEnd = state.md.helpers.parseLinkLabel(state, state.pos + 1, false) + + // parser failed to find ']', so it's not a valid link + if (labelEnd < 0) { + return false + } + + pos = labelEnd + 1 + if (pos < max && state.src.charCodeAt(pos) === 0x28 /* ( */) { + // + // Inline link + // + + // [link]( "title" ) + // ^^ skipping these spaces + pos++ + for (; pos < max; pos++) { + code = state.src.charCodeAt(pos) + if (!md.utils.isSpace(code) && code !== 0x0a) { + break + } + } + if (pos >= max) { + return false + } + + // [link]( "title" ) + // ^^^^^^ parsing link destination + start = pos + res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax) + if (res.ok) { + href = state.md.normalizeLink(res.str) + if (state.md.validateLink(href)) { + pos = res.pos + } else { + href = '' + } + } + + // [link]( "title" ) + // ^^ skipping these spaces + start = pos + for (; pos < max; pos++) { + code = state.src.charCodeAt(pos) + if (!md.utils.isSpace(code) && code !== 0x0a) { + break + } + } + + // [link]( "title" ) + // ^^^^^^^ parsing link title + res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax) + if (pos < max && start !== pos && res.ok) { + title = res.str + pos = res.pos + + // [link]( "title" ) + // ^^ skipping these spaces + for (; pos < max; pos++) { + code = state.src.charCodeAt(pos) + if (!md.utils.isSpace(code) && code !== 0x0a) { + break + } + } + } else { + title = '' + } + + // [link]( "title" =WxH ) + // ^^^^ parsing image size + if (pos - 1 >= 0) { + code = state.src.charCodeAt(pos - 1) + + // there must be at least one white spaces + // between previous field and the size + if (code === 0x20) { + res = parseImageSize(state.src, pos, state.posMax) + if (res.ok) { + width = res.width + height = res.height + pos = res.pos + + // [link]( "title" =WxH ) + // ^^ skipping these spaces + for (; pos < max; pos++) { + code = state.src.charCodeAt(pos) + if (code !== 0x20 && code !== 0x0a) { + break + } + } + } + } + } + + if (pos >= max || state.src.charCodeAt(pos) !== 0x29 /* ) */) { + state.pos = oldPos + return false + } + pos++ + } else { + // + // Link reference + // + if (typeof state.env.references === 'undefined') { + return false + } + + if (pos < max && state.src.charCodeAt(pos) === 0x5b /* [ */) { + start = pos + 1 + pos = state.md.helpers.parseLinkLabel(state, pos) + if (pos >= 0) { + label = state.src.slice(start, pos++) + } else { + pos = labelEnd + 1 + } + } else { + pos = labelEnd + 1 + } + + // covers label === '' and label === undefined + // (collapsed reference link and shortcut reference link respectively) + if (!label) { + label = state.src.slice(labelStart, labelEnd) + } + + ref = state.env.references[md.utils.normalizeReference(label)] + if (!ref) { + state.pos = oldPos + return false + } + href = ref.href + title = ref.title + } + + // + // We found the end of the link, and know for a fact it's a valid link; + // so all that's left to do is to call tokenizer. + // + if (!silent) { + content = state.src.slice(labelStart, labelEnd) + + state.md.inline.parse(content, state.md, state.env, (tokens = [])) + + let div = state.push('image-container-open', 'div', 1) + div.block = true + div.attrs = [ + ['style', `text-align: ${options.hAlign}`] + ] + + token = state.push('image', 'img', 0) + token.attrs = attrs = [ + ['src', href], + ['alt', ''] + ] + token.children = tokens + token.content = content + + if (title) { + attrs.push(['title', title]) + } + + if (width !== '') { + attrs.push(['width', width]) + } + + if (height !== '') { + attrs.push(['height', height]) + } + } + state.push('image-container-close', 'div', -1) + state.pos = pos + state.posMax = max + options.urlSet.add(href) + return true + }) +} diff --git a/src/markdown-it-vue.vue b/src/markdown-it-vue.vue index 6251ba1..32e4d53 100644 --- a/src/markdown-it-vue.vue +++ b/src/markdown-it-vue.vue @@ -1,5 +1,17 @@