From bfb384a6d60652246c387e2f1df8ac7e608fa283 Mon Sep 17 00:00:00 2001 From: y2w8 Date: Sat, 2 May 2026 13:11:13 +0300 Subject: [PATCH 1/2] feat: custom css option. --- README.md | 1 + assets/index.html | 754 +--------------------------------- assets/style.css | 752 +++++++++++++++++++++++++++++++++ lua/markdown_preview/init.lua | 13 + 4 files changed, 767 insertions(+), 753 deletions(-) create mode 100644 assets/style.css diff --git a/README.md b/README.md index 7506dd0..c254b66 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,7 @@ require("markdown_preview").setup({ content_name = "content.md", -- workspace content file index_name = "index.html", -- workspace HTML file + custom_css = "", -- Absolute path, leave it empty for default style workspace_dir = nil, -- nil = auto (shared for takeover, per-buffer for multi) overwrite_index_on_start = true, -- copy plugin's index.html on every start diff --git a/assets/index.html b/assets/index.html index 4dd3148..6912acb 100644 --- a/assets/index.html +++ b/assets/index.html @@ -14,759 +14,7 @@ - + diff --git a/assets/style.css b/assets/style.css new file mode 100644 index 0000000..4ddebf6 --- /dev/null +++ b/assets/style.css @@ -0,0 +1,752 @@ +/* ── CSS Variables ─────────────────────────────────────────────── */ +:root { + --bg: #0d1117; + --panel: #161b22; + --stroke: #30363d; + --fg: #e6edf3; + --fg-muted: #8b949e; + --link: #58a6ff; + --code-bg: #1b2028; + --blockquote-border: #3b434b; + --table-border: #30363d; + --table-row-alt: rgba(255, 255, 255, .03); + --err-bg: rgba(239, 68, 68, .12); + --err-border: rgba(239, 68, 68, .35); + --err-fg: #fecaca; + --scroll-track: transparent; + --scroll-thumb: rgba(148, 163, 184, .35); + --scroll-thumb-hover: rgba(148, 163, 184, .6); + --accent: #58a6ff; + --badge-bg: rgba(255, 255, 255, .06); + --badge-fg: #8b949e; + --skeleton: rgba(255, 255, 255, .04); + --skeleton-shine: rgba(255, 255, 255, .08); + /* GitHub callout colors (dark) */ + --color-note: #2f81f7; + --color-tip: #3fb950; + --color-warning: #d29922; + --color-caution: #f85149; + --color-important: #a371f7; + /* Heading accent colors */ + --color-h1: #58a6ff; + --color-h2: #a371f7; + --color-h3: #3fb950; + --color-h4: #39d2c0; + --color-h5: #d29922; + --color-h6: #8b949e; +} + +[data-theme="light"] { + --bg: #ffffff; + --panel: #f6f8fa; + --stroke: #d0d7de; + --fg: #1f2328; + --fg-muted: #656d76; + --link: #0969da; + --code-bg: #f6f8fa; + --blockquote-border: #d0d7de; + --table-border: #d0d7de; + --table-row-alt: rgba(0, 0, 0, .02); + --err-bg: rgba(239, 68, 68, .08); + --err-border: #fecaca; + --err-fg: #7f1d1d; + --scroll-track: transparent; + --scroll-thumb: rgba(100, 116, 139, .4); + --scroll-thumb-hover: rgba(100, 116, 139, .65); + --accent: #0969da; + --badge-bg: rgba(0, 0, 0, .04); + --badge-fg: #656d76; + --skeleton: rgba(0, 0, 0, .04); + --skeleton-shine: rgba(0, 0, 0, .07); + /* GitHub callout colors (light) */ + --color-note: #0969da; + --color-tip: #1a7f37; + --color-warning: #9a6700; + --color-caution: #d1242f; + --color-important: #8250df; + /* Heading accent colors */ + --color-h1: #0969da; + --color-h2: #8250df; + --color-h3: #1a7f37; + --color-h4: #0e8a7e; + --color-h5: #9a6700; + --color-h6: #656d76; +} + +/* ── Reset & base ──────────────────────────────────────────────── */ +*, +*::before, +*::after { + box-sizing: border-box +} + +html { + scrollbar-width: thin; + scrollbar-color: var(--scroll-thumb) var(--scroll-track); +} + +html, +body { + height: 100%; + margin: 0; + background: var(--bg); + color: var(--fg); + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif; + line-height: 1.6; + -webkit-font-smoothing: antialiased; +} + +/* ── Header ────────────────────────────────────────────────────── */ +header { + position: sticky; + top: 0; + z-index: 10; + display: flex; + align-items: center; + gap: .6rem; + padding: .55rem 1.2rem; + background: var(--panel); + border-bottom: 1px solid var(--stroke); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); +} + +header h1 { + margin: 0; + font-size: .9rem; + font-weight: 600; + letter-spacing: .2px; +} + +.header-icon { + display: flex; + align-items: center; + color: var(--fg-muted); +} + +.spacer { + flex: 1 +} + +/* Connection dot */ +.status-dot { + width: 7px; + height: 7px; + border-radius: 50%; + background: var(--fg-muted); + opacity: .4; + transition: all .3s; + flex-shrink: 0; +} + +.status-dot.connected { + background: #3fb950; + opacity: 1; + box-shadow: 0 0 6px rgba(63, 185, 80, .5); +} + +.status-dot.error { + background: #f85149; + opacity: 1; +} + +#status { + font-size: .75rem; + color: var(--fg-muted); +} + +.btn { + background: transparent; + border: 1px solid var(--stroke); + color: var(--fg-muted); + padding: .35rem; + border-radius: 8px; + cursor: pointer; + font-size: .82rem; + font-weight: 500; + transition: border-color .15s, background .15s, color .15s; + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; +} + +.btn:hover { + background: rgba(127, 127, 127, .1); + color: var(--fg); +} + +.btn-text { + width: auto; + padding: .35rem .65rem; +} + +/* ── Loading skeleton ─────────────────────────────────────────── */ +.skeleton { + padding: 2rem; + max-width: 900px; + margin: 0 auto; +} + +.skeleton-line { + height: 14px; + border-radius: 6px; + background: var(--skeleton); + margin-bottom: 12px; + position: relative; + overflow: hidden; +} + +.skeleton-line::after { + content: ''; + position: absolute; + inset: 0; + background: linear-gradient(90deg, transparent, var(--skeleton-shine), transparent); + animation: shimmer 1.5s infinite; +} + +.skeleton-line:nth-child(1) { + width: 45%; + height: 28px; + margin-bottom: 20px; +} + +.skeleton-line:nth-child(2) { + width: 90% +} + +.skeleton-line:nth-child(3) { + width: 75% +} + +.skeleton-line:nth-child(4) { + width: 85% +} + +.skeleton-line:nth-child(5) { + width: 60% +} + +.skeleton-line:nth-child(6) { + width: 0; + height: 8px +} + +.skeleton-line:nth-child(7) { + width: 35%; + height: 22px; + margin-bottom: 16px +} + +.skeleton-line:nth-child(8) { + width: 80% +} + +.skeleton-line:nth-child(9) { + width: 70% +} + +@keyframes shimmer { + 0% { + transform: translateX(-100%) + } + + 100% { + transform: translateX(100%) + } +} + +/* ── Markdown content ──────────────────────────────────────────── */ +#content { + max-width: 900px; + margin: 0 auto; + padding: 2rem 2rem 4rem; + animation: fadeIn .2s ease; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(4px) + } + + to { + opacity: 1; + transform: none + } +} + +#content>*:first-child { + margin-top: 0 +} + +/* Headings */ +#content h1, +#content h2, +#content h3, +#content h4, +#content h5, +#content h6 { + position: relative; + scroll-margin-top: 3.2rem; +} + +#content h1 { + font-size: 2em; + border-bottom: 1px solid var(--stroke); + border-left: 3px solid var(--color-h1); + padding-bottom: .3em; + padding-left: .6em; + margin: 1.5em 0 .5em; +} + +#content h2 { + font-size: 1.5em; + border-bottom: 1px solid var(--stroke); + border-left: 3px solid var(--color-h2); + padding-bottom: .25em; + padding-left: .6em; + margin: 1.4em 0 .5em; +} + +#content h3 { + font-size: 1.25em; + border-left: 3px solid var(--color-h3); + padding-left: .6em; + margin: 1.3em 0 .4em; +} + +#content h4 { + font-size: 1em; + border-left: 3px solid var(--color-h4); + padding-left: .6em; + margin: 1.2em 0 .4em; +} + +#content h5 { + font-size: .875em; + color: var(--fg-muted); + border-left: 3px solid var(--color-h5); + padding-left: .6em; + margin: 1em 0 .4em; +} + +#content h6 { + font-size: .875em; + color: var(--fg-muted); + border-left: 3px solid var(--color-h6); + padding-left: .6em; + margin: 1em 0 .4em; +} + + +/* Paragraphs & text */ +#content p { + margin: 0 0 1em; +} + +#content a { + color: var(--link); + text-decoration: none; +} + +#content a:hover { + text-decoration: underline; +} + +#content strong { + font-weight: 600 +} + +#content img { + max-width: 100%; + border-radius: 6px; +} + +#content hr { + height: 3px; + background: var(--stroke); + border: none; + margin: 1.5em 0; +} + +/* Lists */ +#content ul, +#content ol { + padding-left: 2em; + margin: 0 0 1em; +} + +#content li+li { + margin-top: .25em +} + +/* Task lists */ +#content .task-list-item { + list-style: none; + margin-left: -1.5em; +} + +#content .task-list-item input[type="checkbox"] { + margin-right: .4em; +} + +/* Blockquotes */ +#content blockquote { + margin: 0 0 1em; + padding: .5em 1em; + border-left: 4px solid var(--blockquote-border); + color: var(--fg-muted); +} + +#content blockquote>*:last-child { + margin-bottom: 0 +} + +/* Tables */ +#content table { + width: 100%; + border-collapse: collapse; + margin: 0 0 1em; + font-size: .9em; +} + +#content th, +#content td { + padding: .5em .8em; + border: 1px solid var(--table-border); +} + +#content th { + background: var(--panel); + font-weight: 600; +} + +#content tr:nth-child(even) { + background: var(--table-row-alt); +} + +/* Inline code */ +#content code { + background: var(--code-bg); + padding: .15em .35em; + border-radius: 4px; + font-size: .88em; + font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; +} + +/* Code blocks */ +#content pre { + position: relative; + background: var(--code-bg); + border: 1px solid var(--stroke); + border-radius: 8px; + padding: 1em; + overflow-x: auto; + margin: 0 0 1em; + scrollbar-width: thin; + scrollbar-color: var(--scroll-thumb) transparent; +} + +#content pre code { + background: none; + padding: 0; + border-radius: 0; + font-size: .85em; + line-height: 1.55; +} + +/* Language badge on code blocks */ +#content pre[data-lang]::before { + content: attr(data-lang); + position: absolute; + top: 0; + right: 0; + padding: .2em .6em; + font-size: .68rem; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + color: var(--badge-fg); + background: var(--badge-bg); + border-bottom-left-radius: 6px; + border-top-right-radius: 7px; + text-transform: uppercase; + letter-spacing: .5px; + font-weight: 500; + line-height: 1.4; +} + +/* ── Copy button on code blocks ──────────────────────────────── */ +#content pre .copy-btn { + position: absolute; + top: 6px; + right: 6px; + width: 28px; + height: 28px; + display: flex; + align-items: center; + justify-content: center; + background: var(--panel); + border: 1px solid var(--stroke); + border-radius: 6px; + cursor: pointer; + opacity: 0; + transition: opacity .15s, background .15s; + color: var(--fg-muted); + padding: 0; + z-index: 2; +} + +#content pre:hover .copy-btn { + opacity: 1; +} + +#content pre .copy-btn:hover { + color: var(--fg); + background: rgba(127, 127, 127, .15); +} + +#content pre .copy-btn.copied { + color: #3fb950; +} + +/* Shift badge down when copy button is present */ +#content pre[data-lang] .copy-btn { + top: 26px; +} + +/* ── GitHub callouts / admonitions ────────────────────────────── */ +#content .markdown-alert { + padding: .5rem 1em; + margin-bottom: 16px; + color: inherit; + border-left: .25em solid #888; + border-radius: 0 6px 6px 0; + background: var(--badge-bg); +} + +#content .markdown-alert>:first-child { + margin-top: 0; +} + +#content .markdown-alert>:last-child { + margin-bottom: 0; +} + +#content .markdown-alert .markdown-alert-title { + display: flex; + font-weight: 500; + align-items: center; + line-height: 1; + margin-bottom: .5em; +} + +#content .markdown-alert .markdown-alert-title .octicon { + margin-right: .5rem; + display: inline-block; + overflow: visible !important; + vertical-align: text-bottom; + fill: currentColor; +} + +#content .markdown-alert.markdown-alert-note { + border-left-color: var(--color-note); +} + +#content .markdown-alert.markdown-alert-note .markdown-alert-title { + color: var(--color-note); +} + +#content .markdown-alert.markdown-alert-tip { + border-left-color: var(--color-tip); +} + +#content .markdown-alert.markdown-alert-tip .markdown-alert-title { + color: var(--color-tip); +} + +#content .markdown-alert.markdown-alert-warning { + border-left-color: var(--color-warning); +} + +#content .markdown-alert.markdown-alert-warning .markdown-alert-title { + color: var(--color-warning); +} + +#content .markdown-alert.markdown-alert-important { + border-left-color: var(--color-important); +} + +#content .markdown-alert.markdown-alert-important .markdown-alert-title { + color: var(--color-important); +} + +#content .markdown-alert.markdown-alert-caution { + border-left-color: var(--color-caution); +} + +#content .markdown-alert.markdown-alert-caution .markdown-alert-title { + color: var(--color-caution); +} + +/* ── Footnotes ───────────────────────────────────────────────── */ +#content .footnotes-sep { + margin-top: 2em; +} + +#content .footnotes { + font-size: .88em; + color: var(--fg-muted); +} + +#content .footnotes ol { + padding-left: 1.5em; +} + +#content .footnote-ref a { + text-decoration: none; + font-weight: 600; +} + +#content .footnote-backref { + text-decoration: none; + font-size: .8em; + margin-left: .3em; +} + +/* ── Mermaid diagrams ──────────────────────────────────────────── */ +.mermaid-block { + position: relative; + margin: 1em 0; + border: 1px solid var(--stroke); + border-radius: 10px; + background: var(--panel); + overflow: hidden; + min-height: 60px; +} + +.mermaid-block .mermaid-svg-wrap { + padding: 1rem; + display: flex; + justify-content: center; + overflow: auto; +} + +.mermaid-block .mermaid-svg-wrap svg { + max-width: 100%; + height: auto; +} + +.mermaid-block .mermaid-expand-btn { + position: absolute; + top: 8px; + right: 8px; + z-index: 2; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + background: var(--panel); + border: 1px solid var(--stroke); + border-radius: 6px; + cursor: pointer; + opacity: 0; + transition: opacity .2s; + color: var(--fg-muted); +} + +.mermaid-block:hover .mermaid-expand-btn { + opacity: 1 +} + +.mermaid-block .mermaid-expand-btn:hover { + color: var(--fg); + background: rgba(127, 127, 127, .1); +} + +.mermaid-block .mermaid-error { + padding: .6rem 1rem; + font-size: .85rem; + color: var(--err-fg); + background: var(--err-bg); + border: 1px solid var(--err-border); + border-radius: 6px; + margin: .5rem; +} + +/* Hide Mermaid's built-in error artifacts (NOT .messageText — used for sequence diagram labels) */ +.mermaid-block :where(.error, .error-icon, .error-text, .errorText) { + display: none !important +} + +/* ── Fullscreen overlay (mermaid zoom/pan) ─────────────────────── */ +#overlay { + display: none; + position: fixed; + inset: 0; + z-index: 100; + background: var(--bg); + flex-direction: column; +} + +#overlay.active { + display: flex +} + +#overlay-toolbar { + display: flex; + gap: .4rem; + align-items: center; + padding: .5rem 1rem; + background: var(--panel); + border-bottom: 1px solid var(--stroke); + flex-wrap: wrap; +} + +#overlay-toolbar .sep { + width: 1px; + height: 24px; + background: var(--stroke); + margin: 0 .2rem; +} + +#overlay-toolbar .grow { + flex: 1 +} + +#overlay-panzoom { + flex: 1; + overflow: auto; + cursor: grab; + scrollbar-width: thin; + scrollbar-color: var(--scroll-thumb) var(--scroll-track); +} + +#overlay-panzoom-inner { + min-width: 100%; + min-height: 100%; + box-sizing: border-box; + padding: 1rem; + display: flex; + justify-content: center; + align-items: flex-start; + width: max-content; + height: max-content; +} + +#overlay-panzoom.dragging { + cursor: grabbing +} + +#overlay-panzoom-inner svg { + display: block +} + +/* ── Misc ──────────────────────────────────────────────────────── */ +@media (max-width: 768px) { + #content { + padding: 1rem 1rem 3rem + } +} + diff --git a/lua/markdown_preview/init.lua b/lua/markdown_preview/init.lua index 9cff795..32cdcbc 100644 --- a/lua/markdown_preview/init.lua +++ b/lua/markdown_preview/init.lua @@ -20,6 +20,7 @@ M.config = { content_name = "content.md", index_name = "index.html", + custom_css = "", -- nil = per-buffer workspace (recommended); set a path to override workspace_dir = nil, @@ -95,6 +96,18 @@ local function write_index(dir) end local content = util.read_text(src) content = content:gsub("__BOTTOM_PADDING__", tostring(M.config.bottom_padding)) + + -- Inline custom CSS if configured + if M.config.custom_css and M.config.custom_css ~= "" then + local css_src = vim.fn.expand(M.config.custom_css) + if vim.fn.filereadable(css_src) == 1 then + local css = util.read_text(css_src) + content = content:gsub("", "\n") + else + vim.notify("Markdown Preview: custom_css not found: " .. css_src, vim.log.levels.WARN) + end + end + util.write_text(dst, content) return dst end From f95ab0eb5c44f498170221f14c02393ff6b0fcc0 Mon Sep 17 00:00:00 2001 From: y2w8 Date: Mon, 25 May 2026 19:10:21 +0300 Subject: [PATCH 2/2] Include bundled style in index.html --- assets/index.html | 754 +++++++++++++++++++++++++++++++++- assets/style.css | 752 --------------------------------- lua/markdown_preview/init.lua | 2 +- 3 files changed, 754 insertions(+), 754 deletions(-) delete mode 100644 assets/style.css diff --git a/assets/index.html b/assets/index.html index 6912acb..4dd3148 100644 --- a/assets/index.html +++ b/assets/index.html @@ -14,7 +14,759 @@ - + diff --git a/assets/style.css b/assets/style.css deleted file mode 100644 index 4ddebf6..0000000 --- a/assets/style.css +++ /dev/null @@ -1,752 +0,0 @@ -/* ── CSS Variables ─────────────────────────────────────────────── */ -:root { - --bg: #0d1117; - --panel: #161b22; - --stroke: #30363d; - --fg: #e6edf3; - --fg-muted: #8b949e; - --link: #58a6ff; - --code-bg: #1b2028; - --blockquote-border: #3b434b; - --table-border: #30363d; - --table-row-alt: rgba(255, 255, 255, .03); - --err-bg: rgba(239, 68, 68, .12); - --err-border: rgba(239, 68, 68, .35); - --err-fg: #fecaca; - --scroll-track: transparent; - --scroll-thumb: rgba(148, 163, 184, .35); - --scroll-thumb-hover: rgba(148, 163, 184, .6); - --accent: #58a6ff; - --badge-bg: rgba(255, 255, 255, .06); - --badge-fg: #8b949e; - --skeleton: rgba(255, 255, 255, .04); - --skeleton-shine: rgba(255, 255, 255, .08); - /* GitHub callout colors (dark) */ - --color-note: #2f81f7; - --color-tip: #3fb950; - --color-warning: #d29922; - --color-caution: #f85149; - --color-important: #a371f7; - /* Heading accent colors */ - --color-h1: #58a6ff; - --color-h2: #a371f7; - --color-h3: #3fb950; - --color-h4: #39d2c0; - --color-h5: #d29922; - --color-h6: #8b949e; -} - -[data-theme="light"] { - --bg: #ffffff; - --panel: #f6f8fa; - --stroke: #d0d7de; - --fg: #1f2328; - --fg-muted: #656d76; - --link: #0969da; - --code-bg: #f6f8fa; - --blockquote-border: #d0d7de; - --table-border: #d0d7de; - --table-row-alt: rgba(0, 0, 0, .02); - --err-bg: rgba(239, 68, 68, .08); - --err-border: #fecaca; - --err-fg: #7f1d1d; - --scroll-track: transparent; - --scroll-thumb: rgba(100, 116, 139, .4); - --scroll-thumb-hover: rgba(100, 116, 139, .65); - --accent: #0969da; - --badge-bg: rgba(0, 0, 0, .04); - --badge-fg: #656d76; - --skeleton: rgba(0, 0, 0, .04); - --skeleton-shine: rgba(0, 0, 0, .07); - /* GitHub callout colors (light) */ - --color-note: #0969da; - --color-tip: #1a7f37; - --color-warning: #9a6700; - --color-caution: #d1242f; - --color-important: #8250df; - /* Heading accent colors */ - --color-h1: #0969da; - --color-h2: #8250df; - --color-h3: #1a7f37; - --color-h4: #0e8a7e; - --color-h5: #9a6700; - --color-h6: #656d76; -} - -/* ── Reset & base ──────────────────────────────────────────────── */ -*, -*::before, -*::after { - box-sizing: border-box -} - -html { - scrollbar-width: thin; - scrollbar-color: var(--scroll-thumb) var(--scroll-track); -} - -html, -body { - height: 100%; - margin: 0; - background: var(--bg); - color: var(--fg); - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif; - line-height: 1.6; - -webkit-font-smoothing: antialiased; -} - -/* ── Header ────────────────────────────────────────────────────── */ -header { - position: sticky; - top: 0; - z-index: 10; - display: flex; - align-items: center; - gap: .6rem; - padding: .55rem 1.2rem; - background: var(--panel); - border-bottom: 1px solid var(--stroke); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); -} - -header h1 { - margin: 0; - font-size: .9rem; - font-weight: 600; - letter-spacing: .2px; -} - -.header-icon { - display: flex; - align-items: center; - color: var(--fg-muted); -} - -.spacer { - flex: 1 -} - -/* Connection dot */ -.status-dot { - width: 7px; - height: 7px; - border-radius: 50%; - background: var(--fg-muted); - opacity: .4; - transition: all .3s; - flex-shrink: 0; -} - -.status-dot.connected { - background: #3fb950; - opacity: 1; - box-shadow: 0 0 6px rgba(63, 185, 80, .5); -} - -.status-dot.error { - background: #f85149; - opacity: 1; -} - -#status { - font-size: .75rem; - color: var(--fg-muted); -} - -.btn { - background: transparent; - border: 1px solid var(--stroke); - color: var(--fg-muted); - padding: .35rem; - border-radius: 8px; - cursor: pointer; - font-size: .82rem; - font-weight: 500; - transition: border-color .15s, background .15s, color .15s; - display: flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; -} - -.btn:hover { - background: rgba(127, 127, 127, .1); - color: var(--fg); -} - -.btn-text { - width: auto; - padding: .35rem .65rem; -} - -/* ── Loading skeleton ─────────────────────────────────────────── */ -.skeleton { - padding: 2rem; - max-width: 900px; - margin: 0 auto; -} - -.skeleton-line { - height: 14px; - border-radius: 6px; - background: var(--skeleton); - margin-bottom: 12px; - position: relative; - overflow: hidden; -} - -.skeleton-line::after { - content: ''; - position: absolute; - inset: 0; - background: linear-gradient(90deg, transparent, var(--skeleton-shine), transparent); - animation: shimmer 1.5s infinite; -} - -.skeleton-line:nth-child(1) { - width: 45%; - height: 28px; - margin-bottom: 20px; -} - -.skeleton-line:nth-child(2) { - width: 90% -} - -.skeleton-line:nth-child(3) { - width: 75% -} - -.skeleton-line:nth-child(4) { - width: 85% -} - -.skeleton-line:nth-child(5) { - width: 60% -} - -.skeleton-line:nth-child(6) { - width: 0; - height: 8px -} - -.skeleton-line:nth-child(7) { - width: 35%; - height: 22px; - margin-bottom: 16px -} - -.skeleton-line:nth-child(8) { - width: 80% -} - -.skeleton-line:nth-child(9) { - width: 70% -} - -@keyframes shimmer { - 0% { - transform: translateX(-100%) - } - - 100% { - transform: translateX(100%) - } -} - -/* ── Markdown content ──────────────────────────────────────────── */ -#content { - max-width: 900px; - margin: 0 auto; - padding: 2rem 2rem 4rem; - animation: fadeIn .2s ease; -} - -@keyframes fadeIn { - from { - opacity: 0; - transform: translateY(4px) - } - - to { - opacity: 1; - transform: none - } -} - -#content>*:first-child { - margin-top: 0 -} - -/* Headings */ -#content h1, -#content h2, -#content h3, -#content h4, -#content h5, -#content h6 { - position: relative; - scroll-margin-top: 3.2rem; -} - -#content h1 { - font-size: 2em; - border-bottom: 1px solid var(--stroke); - border-left: 3px solid var(--color-h1); - padding-bottom: .3em; - padding-left: .6em; - margin: 1.5em 0 .5em; -} - -#content h2 { - font-size: 1.5em; - border-bottom: 1px solid var(--stroke); - border-left: 3px solid var(--color-h2); - padding-bottom: .25em; - padding-left: .6em; - margin: 1.4em 0 .5em; -} - -#content h3 { - font-size: 1.25em; - border-left: 3px solid var(--color-h3); - padding-left: .6em; - margin: 1.3em 0 .4em; -} - -#content h4 { - font-size: 1em; - border-left: 3px solid var(--color-h4); - padding-left: .6em; - margin: 1.2em 0 .4em; -} - -#content h5 { - font-size: .875em; - color: var(--fg-muted); - border-left: 3px solid var(--color-h5); - padding-left: .6em; - margin: 1em 0 .4em; -} - -#content h6 { - font-size: .875em; - color: var(--fg-muted); - border-left: 3px solid var(--color-h6); - padding-left: .6em; - margin: 1em 0 .4em; -} - - -/* Paragraphs & text */ -#content p { - margin: 0 0 1em; -} - -#content a { - color: var(--link); - text-decoration: none; -} - -#content a:hover { - text-decoration: underline; -} - -#content strong { - font-weight: 600 -} - -#content img { - max-width: 100%; - border-radius: 6px; -} - -#content hr { - height: 3px; - background: var(--stroke); - border: none; - margin: 1.5em 0; -} - -/* Lists */ -#content ul, -#content ol { - padding-left: 2em; - margin: 0 0 1em; -} - -#content li+li { - margin-top: .25em -} - -/* Task lists */ -#content .task-list-item { - list-style: none; - margin-left: -1.5em; -} - -#content .task-list-item input[type="checkbox"] { - margin-right: .4em; -} - -/* Blockquotes */ -#content blockquote { - margin: 0 0 1em; - padding: .5em 1em; - border-left: 4px solid var(--blockquote-border); - color: var(--fg-muted); -} - -#content blockquote>*:last-child { - margin-bottom: 0 -} - -/* Tables */ -#content table { - width: 100%; - border-collapse: collapse; - margin: 0 0 1em; - font-size: .9em; -} - -#content th, -#content td { - padding: .5em .8em; - border: 1px solid var(--table-border); -} - -#content th { - background: var(--panel); - font-weight: 600; -} - -#content tr:nth-child(even) { - background: var(--table-row-alt); -} - -/* Inline code */ -#content code { - background: var(--code-bg); - padding: .15em .35em; - border-radius: 4px; - font-size: .88em; - font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; -} - -/* Code blocks */ -#content pre { - position: relative; - background: var(--code-bg); - border: 1px solid var(--stroke); - border-radius: 8px; - padding: 1em; - overflow-x: auto; - margin: 0 0 1em; - scrollbar-width: thin; - scrollbar-color: var(--scroll-thumb) transparent; -} - -#content pre code { - background: none; - padding: 0; - border-radius: 0; - font-size: .85em; - line-height: 1.55; -} - -/* Language badge on code blocks */ -#content pre[data-lang]::before { - content: attr(data-lang); - position: absolute; - top: 0; - right: 0; - padding: .2em .6em; - font-size: .68rem; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; - color: var(--badge-fg); - background: var(--badge-bg); - border-bottom-left-radius: 6px; - border-top-right-radius: 7px; - text-transform: uppercase; - letter-spacing: .5px; - font-weight: 500; - line-height: 1.4; -} - -/* ── Copy button on code blocks ──────────────────────────────── */ -#content pre .copy-btn { - position: absolute; - top: 6px; - right: 6px; - width: 28px; - height: 28px; - display: flex; - align-items: center; - justify-content: center; - background: var(--panel); - border: 1px solid var(--stroke); - border-radius: 6px; - cursor: pointer; - opacity: 0; - transition: opacity .15s, background .15s; - color: var(--fg-muted); - padding: 0; - z-index: 2; -} - -#content pre:hover .copy-btn { - opacity: 1; -} - -#content pre .copy-btn:hover { - color: var(--fg); - background: rgba(127, 127, 127, .15); -} - -#content pre .copy-btn.copied { - color: #3fb950; -} - -/* Shift badge down when copy button is present */ -#content pre[data-lang] .copy-btn { - top: 26px; -} - -/* ── GitHub callouts / admonitions ────────────────────────────── */ -#content .markdown-alert { - padding: .5rem 1em; - margin-bottom: 16px; - color: inherit; - border-left: .25em solid #888; - border-radius: 0 6px 6px 0; - background: var(--badge-bg); -} - -#content .markdown-alert>:first-child { - margin-top: 0; -} - -#content .markdown-alert>:last-child { - margin-bottom: 0; -} - -#content .markdown-alert .markdown-alert-title { - display: flex; - font-weight: 500; - align-items: center; - line-height: 1; - margin-bottom: .5em; -} - -#content .markdown-alert .markdown-alert-title .octicon { - margin-right: .5rem; - display: inline-block; - overflow: visible !important; - vertical-align: text-bottom; - fill: currentColor; -} - -#content .markdown-alert.markdown-alert-note { - border-left-color: var(--color-note); -} - -#content .markdown-alert.markdown-alert-note .markdown-alert-title { - color: var(--color-note); -} - -#content .markdown-alert.markdown-alert-tip { - border-left-color: var(--color-tip); -} - -#content .markdown-alert.markdown-alert-tip .markdown-alert-title { - color: var(--color-tip); -} - -#content .markdown-alert.markdown-alert-warning { - border-left-color: var(--color-warning); -} - -#content .markdown-alert.markdown-alert-warning .markdown-alert-title { - color: var(--color-warning); -} - -#content .markdown-alert.markdown-alert-important { - border-left-color: var(--color-important); -} - -#content .markdown-alert.markdown-alert-important .markdown-alert-title { - color: var(--color-important); -} - -#content .markdown-alert.markdown-alert-caution { - border-left-color: var(--color-caution); -} - -#content .markdown-alert.markdown-alert-caution .markdown-alert-title { - color: var(--color-caution); -} - -/* ── Footnotes ───────────────────────────────────────────────── */ -#content .footnotes-sep { - margin-top: 2em; -} - -#content .footnotes { - font-size: .88em; - color: var(--fg-muted); -} - -#content .footnotes ol { - padding-left: 1.5em; -} - -#content .footnote-ref a { - text-decoration: none; - font-weight: 600; -} - -#content .footnote-backref { - text-decoration: none; - font-size: .8em; - margin-left: .3em; -} - -/* ── Mermaid diagrams ──────────────────────────────────────────── */ -.mermaid-block { - position: relative; - margin: 1em 0; - border: 1px solid var(--stroke); - border-radius: 10px; - background: var(--panel); - overflow: hidden; - min-height: 60px; -} - -.mermaid-block .mermaid-svg-wrap { - padding: 1rem; - display: flex; - justify-content: center; - overflow: auto; -} - -.mermaid-block .mermaid-svg-wrap svg { - max-width: 100%; - height: auto; -} - -.mermaid-block .mermaid-expand-btn { - position: absolute; - top: 8px; - right: 8px; - z-index: 2; - width: 32px; - height: 32px; - display: flex; - align-items: center; - justify-content: center; - background: var(--panel); - border: 1px solid var(--stroke); - border-radius: 6px; - cursor: pointer; - opacity: 0; - transition: opacity .2s; - color: var(--fg-muted); -} - -.mermaid-block:hover .mermaid-expand-btn { - opacity: 1 -} - -.mermaid-block .mermaid-expand-btn:hover { - color: var(--fg); - background: rgba(127, 127, 127, .1); -} - -.mermaid-block .mermaid-error { - padding: .6rem 1rem; - font-size: .85rem; - color: var(--err-fg); - background: var(--err-bg); - border: 1px solid var(--err-border); - border-radius: 6px; - margin: .5rem; -} - -/* Hide Mermaid's built-in error artifacts (NOT .messageText — used for sequence diagram labels) */ -.mermaid-block :where(.error, .error-icon, .error-text, .errorText) { - display: none !important -} - -/* ── Fullscreen overlay (mermaid zoom/pan) ─────────────────────── */ -#overlay { - display: none; - position: fixed; - inset: 0; - z-index: 100; - background: var(--bg); - flex-direction: column; -} - -#overlay.active { - display: flex -} - -#overlay-toolbar { - display: flex; - gap: .4rem; - align-items: center; - padding: .5rem 1rem; - background: var(--panel); - border-bottom: 1px solid var(--stroke); - flex-wrap: wrap; -} - -#overlay-toolbar .sep { - width: 1px; - height: 24px; - background: var(--stroke); - margin: 0 .2rem; -} - -#overlay-toolbar .grow { - flex: 1 -} - -#overlay-panzoom { - flex: 1; - overflow: auto; - cursor: grab; - scrollbar-width: thin; - scrollbar-color: var(--scroll-thumb) var(--scroll-track); -} - -#overlay-panzoom-inner { - min-width: 100%; - min-height: 100%; - box-sizing: border-box; - padding: 1rem; - display: flex; - justify-content: center; - align-items: flex-start; - width: max-content; - height: max-content; -} - -#overlay-panzoom.dragging { - cursor: grabbing -} - -#overlay-panzoom-inner svg { - display: block -} - -/* ── Misc ──────────────────────────────────────────────────────── */ -@media (max-width: 768px) { - #content { - padding: 1rem 1rem 3rem - } -} - diff --git a/lua/markdown_preview/init.lua b/lua/markdown_preview/init.lua index 32cdcbc..e4aeaf2 100644 --- a/lua/markdown_preview/init.lua +++ b/lua/markdown_preview/init.lua @@ -102,7 +102,7 @@ local function write_index(dir) local css_src = vim.fn.expand(M.config.custom_css) if vim.fn.filereadable(css_src) == 1 then local css = util.read_text(css_src) - content = content:gsub("", "\n") + content = content:gsub("", function() return "\n" end) else vim.notify("Markdown Preview: custom_css not found: " .. css_src, vim.log.levels.WARN) end