|
| 1 | +const defaultOption = { |
| 2 | + limitless: false, // 限制图片数量 |
| 3 | + limit: 10, // 图片数量上限, |
| 4 | + height: 300, // 组件高度 |
| 5 | +}; |
| 6 | + |
| 7 | +const imageFlowPlugin = (md, opt) => { |
| 8 | + const options = opt || defaultOption; |
| 9 | + const style = { |
| 10 | + IF_layer1: `margin:1em;white-space:normal;border:none;padding:0px;overflow:hidden;height:${options.height}px;line-height:${options.height}px`, |
| 11 | + IF_layer2: `white-space:nowrap;width:100%;overflow-x:scroll;`, |
| 12 | + IF_layer3: `display:inline-block;word-wrap:break-word;white-space:normal;vertical-align:middle;width:100%;`, |
| 13 | + IF_image: `display:inline-block;`, |
| 14 | + }; |
| 15 | + |
| 16 | + const tokenize = (state, silent) => { |
| 17 | + let result = false; |
| 18 | + let token; |
| 19 | + const matchReg = /^<((!\[([^\]])*\]\(([^)])*\)(,?)(\s)*)*)>/; |
| 20 | + |
| 21 | + if (silent) { |
| 22 | + return result; |
| 23 | + } |
| 24 | + if (state.src.charCodeAt(state.pos) !== 0x3c /* < */) { |
| 25 | + return result; |
| 26 | + } |
| 27 | + |
| 28 | + const match = matchReg.exec(state.src.substr(state.pos)); |
| 29 | + |
| 30 | + if (match) { |
| 31 | + if (options.limitless) { |
| 32 | + result = true; |
| 33 | + } else if (match[1].split(/,|\s/).filter((val) => val).length < options.limit) { |
| 34 | + result = true; |
| 35 | + } else { |
| 36 | + return result; |
| 37 | + } |
| 38 | + |
| 39 | + token = state.push("imageFlow_start", "imageFlow", 1); |
| 40 | + token = state.push("imageFlow_content", "imageFlow", 0); |
| 41 | + [, token.content] = match; |
| 42 | + token = state.push("imageFlow_end", "imageFlow", -1); |
| 43 | + |
| 44 | + // update position |
| 45 | + var newline = state.src.indexOf("\n", state.pos); |
| 46 | + if (newline !== -1) { |
| 47 | + state.pos = newline; |
| 48 | + } else { |
| 49 | + state.pos = state.pos + state.posMax + 1; |
| 50 | + } |
| 51 | + } |
| 52 | + |
| 53 | + return result; |
| 54 | + }; |
| 55 | + |
| 56 | + md.renderer.rules.imageFlow_start = () => { |
| 57 | + return `<section style=${style.IF_layer1}><section style=${style.IF_layer2}>`; |
| 58 | + }; |
| 59 | + md.renderer.rules.imageFlow_end = () => { |
| 60 | + return `</section></section>`; |
| 61 | + }; |
| 62 | + md.renderer.rules.imageFlow_content = (tokens, idx) => { |
| 63 | + const contents = tokens[idx].content.split(/,|\s/).filter((val) => val); |
| 64 | + let wrapperContent = ""; |
| 65 | + let image; |
| 66 | + contents.forEach((content) => { |
| 67 | + image = content.split(/\[|\]|\(|\)|!/).filter((val) => val); |
| 68 | + wrapperContent += `<section style=${style.IF_layer3}><img alt=${image[0]} src=${image[1]} style=${ |
| 69 | + style.IF_image |
| 70 | + } /></section>`; |
| 71 | + }); |
| 72 | + |
| 73 | + return wrapperContent; |
| 74 | + }; |
| 75 | + |
| 76 | + md.inline.ruler.before("image", "imageFlow", tokenize); |
| 77 | +}; |
| 78 | + |
| 79 | +export default imageFlowPlugin; |
0 commit comments