diff --git a/README.md b/README.md index 1de946e0..b24fdde0 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Support Katex for rendering math equations in markdown and AsciiDoc files Supports mermaid for rendering diagrams in markdown files +Syntax highlighting for code blocks in Markdown and AsciiDoc + ### Updates See [RELEASE.md](RELEASE.md) @@ -130,12 +132,14 @@ Since this is a young project, there should be a lot of rooms for improvements. ## TODO - [x] Support for KaTex math in Markdown and AsciiDoc - [x] Support for Mermaid diagrams in Markdown +- [x] Syntax highlighting for code blocks in Markdown and AsciiDoc - [ ] Autoscroll in the browser as you scroll in the Markdown and AsciiDoc files in Neovim - [ ] Support for diagrams in AsciiDoc ## Acknowledgements -* [glacambre/firenvim](https://github.com/glacambre/firenvim) for the sha1 function * [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) and [Live Preview](https://marketplace.visualstudio.com/items?itemName=ms-vscode.live-server) for the idea inspiration +* [glacambre/firenvim](https://github.com/glacambre/firenvim) for the sha1 function reference +* [iamcco/markdown-preview.nvim](https://github.com/iamcco/markdown-preview.nvim) for some JavaScript reference * [sindresorhus/github-markdown-css](https://github.com/sindresorhus/github-markdown-css) CSS style for Markdown files * [markedjs/marked](https://github.com/markedjs/marked) for parsing Markdown files * [asciidoctor/asciidoctor.js](https://github.com/asciidoctor/asciidoctor.js) for parsing AsciiDoc files diff --git a/README.vi.md b/README.vi.md index d8e04f1f..53b910fe 100644 --- a/README.vi.md +++ b/README.vi.md @@ -9,6 +9,8 @@ Hỗ trợ Katex để hiển thị các phương trình toán học trong tệp Hỗ trợ mermaid để hiển thị các biểu đồ trong tệp Markdown +Tô sáng cú pháp code trong tệp Markdown và AsciiDoc + ### Cập nhật Xem [RELEASE.md](RELEASE.md) @@ -126,12 +128,14 @@ Vì đây là một dự án khá mới, hẳn sẽ có nhiều điều cần c - [x] Hỗ trợ công thức toán bằng Katex - [x] Hỗ trợ biểu đồ Mermaid trong Markdown +- [x] Tô sáng cú pháp code trong tệp Markdown và AsciiDoc - [ ] Tự động cuộn trang web khi bạn cuộn trong tệp Markdown và AsciiDoc trong Neovim - [ ] Hỗ trợ biểu đồ trong AsciiDoc ## Cảm ơn -* [glacambre/firenvim](https://github.com/glacambre/firenvim) vì hàm sha1 * [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) và [Live Preview](https://marketplace.visualstudio.com/items?itemName=ms-vscode.live-máy chủ) vì ý tưởng +* [glacambre/firenvim](https://github.com/glacambre/firenvim) vì hàm sha1 +* [iamcco/markdown-preview.nvim](https://github.com/iamcco/markdown-preview.nvim) vì một số tham khảo về JavaScript * [sindresorhus/github-markdown-css](https://github.com/sindresorhus/github-markdown-css) CSS cho tệp Markdown * [markedjs/marked](https://github.com/markedjs/marked) cho việc chuyển đổi tệp Markdown thành HTML * [asciidoctor/asciidoctor.js](https://github.com/asciidoctor/asciidoctor.js) cho việc chuyển đổi tệp AsciiDoc thành HTML diff --git a/lua/livepreview/server/Server.lua b/lua/livepreview/server/Server.lua index d9b1dbe5..60230074 100644 --- a/lua/livepreview/server/Server.lua +++ b/lua/livepreview/server/Server.lua @@ -16,7 +16,6 @@ Server.__index = Server local uv = vim.uv local need_scroll = false -local top_line = 1 local filepath = "" local ws_client @@ -36,7 +35,8 @@ local function send_scroll(client) local message = { type = "scroll", filepath = filepath or '', - line = top_line, + cursor = vim.api.nvim_win_get_cursor(0), + length = vim.api.nvim_buf_line_count(0), } websocket.send_json(client, message) need_scroll = false @@ -46,7 +46,6 @@ end vim.api.nvim_create_autocmd("WinScrolled", { callback = function() need_scroll = true - top_line = vim.fn.line("w0") filepath = vim.api.nvim_buf_get_name(0) if ws_client then send_scroll(ws_client) diff --git a/lua/livepreview/template.lua b/lua/livepreview/template.lua index 99e3949a..f6c564e5 100644 --- a/lua/livepreview/template.lua +++ b/lua/livepreview/template.lua @@ -16,8 +16,8 @@ local html_template = function(body, stylesheet, script_tag) - ]] .. script_tag .. [[ + @@ -27,14 +27,13 @@ local html_template = function(body, stylesheet, script_tag) - - ]] end M.md2html = function(md) local script = [[ + ]] diff --git a/static/markdown/line-numbers.js b/static/markdown/line-numbers.js new file mode 100644 index 00000000..e62eed45 --- /dev/null +++ b/static/markdown/line-numbers.js @@ -0,0 +1,44 @@ +// MIT License +// +// Copyright (c) 2017 Brett Walker +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +function injectLinenumbersPlugin(md) { + // + // Inject line numbers for sync scroll. Notes: + // + // - We track only headings and paragraphs, at any level. + // - TODO Footnotes content causes jumps. Level limit filters it automatically. + function injectLineNumbers(tokens, idx, options, env, slf) { + var line + // if (tokens[idx].map && tokens[idx].level === 0) { + if (tokens[idx].map) { + line = tokens[idx].map[0] + tokens[idx].attrJoin('class', 'source-line') + tokens[idx].attrSet('data-source-line', String(line)) + } + return slf.renderToken(tokens, idx, options, env, slf) + } + + md.renderer.rules.paragraph_open = injectLineNumbers + md.renderer.rules.heading_open = injectLineNumbers + md.renderer.rules.list_item_open = injectLineNumbers + md.renderer.rules.table_open = injectLineNumbers +} + diff --git a/static/markdown/main.js b/static/markdown/main.js index d2cf6fc0..7a42adef 100644 --- a/static/markdown/main.js +++ b/static/markdown/main.js @@ -1,25 +1,3 @@ -// const renderer = { -// code({ text, lang, escaped }) { -// const langString = (lang || '').match(/^\S*/)?.[0]; -// const code = text.replace(/\n$/, '') + '\n'; -// if (!langString) { -// return '
' + code + '
'; -// } -// return `
${code}
` -// }, -// }; -// -// marked.use({ renderer }); -// -// const render = (text) => { -// const html = marked.parse(text, { lineNumbers: true }); -// console.log(html); -// document.querySelector('.markdown-body').innerHTML = html; -// } -// -// const markdownText = document.querySelector('.markdown-body').innerHTML; -// render(markdownText); - const md = window.markdownit({ highlight: function(str, lang) { if (lang && hljs.getLanguage(lang)) { @@ -31,9 +9,10 @@ const md = window.markdownit({ return ''; // use external default escaping } }); +md.use(injectLinenumbersPlugin); const render = (text) => { - const html = md.render(text, { lineNumbers: true }); + const html = md.render(text); console.log(html); document.querySelector('.markdown-body').innerHTML = html; hljs.highlightAll(); diff --git a/static/scroll.js b/static/scroll.js index 3563b2ff..106272c8 100644 --- a/static/scroll.js +++ b/static/scroll.js @@ -89,7 +89,7 @@ function relativeScroll(line, ratio, len) { scroll(offsetTop - document.documentElement.clientHeight * ratio) } -export default { +scrollToLine = { relative: function({ cursor, winline, diff --git a/static/ws-client.js b/static/ws-client.js index c81ffa27..ca4af3e6 100644 --- a/static/ws-client.js +++ b/static/ws-client.js @@ -23,6 +23,8 @@ async function connectWebSocket() { socket.onmessage = (event) => { const message = JSON.parse(event.data); + console.log(message); + console.log(message.type === "scroll"); if (message.type === "reload") { console.log("Reload message received"); @@ -34,6 +36,12 @@ async function connectWebSocket() { renderKatex(); renderMermaid(); } + } else if (message.type = "scroll") { + console.log("Scroll message received"); + scrollToLine.middle({ + cursor: message.cursor[1], + len: message.len + }) } };