Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<meta http-equiv="content-style-type" content="text/css">
<meta name="description" content="This is the online markdown editor with live preview.">

<link id="markdown-theme-css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.8.1/github-markdown-light.min.css">
<link rel="stylesheet" type="text/css" href="css/style.css?v=1.10.1">
<link rel="icon" type="image/png" href="favicon.png">
<script type="module" src="/src/main.js?v=1.10.1"></script>
Expand All @@ -31,6 +32,7 @@
<div id="reset-button"><a href="#">Reset</a></div>
<div id="copy-button"><a href="#">Copy</a></div>
<div id="sync-button"><input type="checkbox" id="sync-scroll-checkbox"><label for="sync-scroll-checkbox">Sync scroll</label></div>
<div id="theme-button"><input type="checkbox" id="theme-checkbox"><label for="theme-checkbox">Dark mode</label></div>
</div>
<div id="github"><a href="https://github.com/tanabe/markdown-live-preview"><img src="image/GitHub-Mark-Light-32px.webp"></a></div>
</header>
Expand Down
139 changes: 125 additions & 14 deletions public/css/style.css
Original file line number Diff line number Diff line change
@@ -1,12 +1,112 @@
:root {
--bg-color: #fafafa;
--text-color: #24292e;
--header-bg: #3a3a3a;
--header-text: #f6f8fa;
--border-color: #e1e4e8;
--divider-color: #d1d5da;
--divider-hover: #959da5;
--divider-active: #6a737d;
}

[data-theme="dark"] {
--bg-color: #212121;
--text-color: #E8E8E8;
--header-bg: #1a1a1a;
--header-text: #E8E8E8;
--border-color: #555555;
--divider-color: #4a4a4a;
--divider-hover: #5a5a5a;
--divider-active: #6a6a6a;
}

/* Dark mode overrides for GitHub markdown CSS */
[data-theme="dark"] .markdown-body {
color: #E8E8E8 !important;
background-color: #212121 !important;
}

[data-theme="dark"] #output {
background-color: #212121 !important;
color: #E8E8E8 !important;
}

/* Headings */
[data-theme="dark"] .markdown-body h1,
[data-theme="dark"] .markdown-body h2,
[data-theme="dark"] .markdown-body h3,
[data-theme="dark"] .markdown-body h4,
[data-theme="dark"] .markdown-body h5,
[data-theme="dark"] .markdown-body h6 {
color: #F5F5F5 !important;
border-color: #555555 !important;
}

/* Blockquotes */
[data-theme="dark"] .markdown-body blockquote {
color: #B8B8B8 !important;
border-left-color: #555555 !important;
}

/* Code */
[data-theme="dark"] .markdown-body code {
background-color: rgba(255, 255, 255, 0.1) !important;
color: #F5F5F5 !important;
}

[data-theme="dark"] .markdown-body pre {
background-color: #1a1a1a !important;
border-color: #555555 !important;
}

[data-theme="dark"] .markdown-body pre code {
background-color: transparent !important;
}

/* Tables */
[data-theme="dark"] .markdown-body table {
color: #E8E8E8 !important;
}

[data-theme="dark"] .markdown-body table th,
[data-theme="dark"] .markdown-body table td {
border-color: #555555 !important;
}

[data-theme="dark"] .markdown-body table tr {
background-color: transparent !important;
border-color: #555555 !important;
}

[data-theme="dark"] .markdown-body table tr:nth-child(2n) {
background-color: rgba(255, 255, 255, 0.03) !important;
}

[data-theme="dark"] .markdown-body table th {
background-color: rgba(255, 255, 255, 0.08) !important;
}

/* Links */
[data-theme="dark"] .markdown-body a {
color: #58a6ff !important;
}

/* Horizontal rules */
[data-theme="dark"] .markdown-body hr {
background-color: #555555 !important;
border-color: #555555 !important;
}


html, body {
color: #333;
color: var(--text-color);
overflow-x: hidden;
margin: 0;
padding: 0;
font-family: Helvetica, arial, freesans, clean, sans-serif;
font-size: 1em;
line-height: 1.5em;
background-color: #fff;
background-color: var(--bg-color);
overscroll-behavior-y: none;
}

Expand All @@ -31,7 +131,7 @@ a:link,
a:visited,
a:hover
a:active {
color: #333;
color: var(--text-color);
text-decoration: none;
}

Expand All @@ -45,13 +145,13 @@ header {
align-items: center;
padding: 8px 16px;
width: 100%;
background-color: #444;
background-color: var(--header-bg);
font-size: 12px;
color: #fff;
color: var(--header-text);
}

header a:link, header a:hover, header a:visited, header a:active {
color: #fff;
color: var(--header-text);
}

header a:hover {
Expand All @@ -78,6 +178,14 @@ header a:hover {
user-select: none;
}

#theme-button {
margin-left: 16px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

header input[type="checkbox"] {
vertical-align: middle;
margin-right: 4px;
Expand All @@ -103,8 +211,8 @@ footer {
bottom: 0;
left: 0;
width: 100%;
background-color: #fff;
color: #fff;
background-color: var(--bg-color);
color: var(--header-text);
text-align: center;
justify-content: center;
align-items: center;
Expand All @@ -115,8 +223,8 @@ footer {
overflow: hidden;
width: 100%;
margin: 0 auto;
background-color: #fff;
border-bottom: 1px solid #e8e8e8;
background-color: var(--bg-color);
border-bottom: 1px solid var(--border-color);
display: flex;
}

Expand All @@ -130,6 +238,8 @@ footer {

#preview-wrapper {
padding: 8px 16px 16px 16px;
background-color: var(--bg-color);
color: var(--text-color);
}

.column {
Expand All @@ -143,6 +253,7 @@ footer {
#preview.column {
overflow-y: scroll;
white-space: normal;
background-color: var(--bg-color);
}

.split-container {
Expand All @@ -158,15 +269,15 @@ footer {

.split-divider {
width: 5px;
background: #ccc;
background: var(--divider-color);
cursor: col-resize;
z-index: 1;
}

.split-divider.hover {
background: #999;
background: var(--divider-hover);
}

.split-divider.active {
background: #666;
}
background: var(--divider-active);
}
56 changes: 54 additions & 2 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import Storehouse from 'storehouse-js';
import * as monaco from 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/+esm';
import { marked } from 'marked';
import DOMPurify from 'dompurify';
import 'github-markdown-css/github-markdown-light.css';

const init = () => {
let hasEdited = false;
Expand All @@ -11,6 +10,7 @@ const init = () => {
const localStorageNamespace = 'com.markdownlivepreview';
const localStorageKey = 'last_state';
const localStorageScrollBarKey = 'scroll_bar_settings';
const localStorageThemeKey = 'theme_preference';
const confirmationMessage = 'Are you sure you want to reset? Your changes will be lost.';
// default template
const defaultInput = `# Markdown syntax guide
Expand Down Expand Up @@ -105,7 +105,8 @@ This web site is using ${"`"}markedjs/marked${"`"}.
hover: { enabled: false },
quickSuggestions: false,
suggestOnTriggerCharacters: false,
folding: false
folding: false,
theme: 'vs'
});

editor.onDidChangeModelContent(() => {
Expand Down Expand Up @@ -260,6 +261,49 @@ This web site is using ${"`"}markedjs/marked${"`"}.
Storehouse.setItem(localStorageNamespace, localStorageScrollBarKey, settings, expiredAt);
};

let loadThemePreference = () => {
let theme = Storehouse.getItem(localStorageNamespace, localStorageThemeKey);
return theme || 'light';
};

let saveThemePreference = (theme) => {
let expiredAt = new Date(2099, 1, 1);
Storehouse.setItem(localStorageNamespace, localStorageThemeKey, theme, expiredAt);
};

let applyTheme = (theme) => {
// Update data attribute for CSS variables
document.documentElement.setAttribute('data-theme', theme === 'dark' ? 'dark' : '');

// Update Monaco editor theme
monaco.editor.setTheme(theme === 'dark' ? 'vs-dark' : 'vs');

// Update markdown CSS link
const markdownLink = document.getElementById('markdown-theme-css');
if (markdownLink) {
if (theme === 'dark') {
markdownLink.href = 'https://cdn.jsdelivr.net/npm/github-markdown-css@5.8.1/github-markdown-dark.min.css';
} else {
markdownLink.href = 'https://cdn.jsdelivr.net/npm/github-markdown-css@5.8.1/github-markdown-light.min.css';
}
}
};

let setupThemeToggle = () => {
const themeCheckbox = document.getElementById('theme-checkbox');
const currentTheme = loadThemePreference();

// Set initial checkbox state
themeCheckbox.checked = currentTheme === 'dark';

// Handle theme toggle
themeCheckbox.addEventListener('change', (event) => {
const newTheme = event.target.checked ? 'dark' : 'light';
saveThemePreference(newTheme);
applyTheme(newTheme);
});
};

let setupDivider = () => {
let lastLeftRatio = 0.5;
const divider = document.getElementById('split-divider');
Expand Down Expand Up @@ -346,6 +390,14 @@ This web site is using ${"`"}markedjs/marked${"`"}.
}
setupResetButton();
setupCopyButton(editor);

// Initialize theme
const currentTheme = loadThemePreference();

// Apply theme settings
applyTheme(currentTheme);

setupThemeToggle();

let scrollBarSettings = loadScrollBarSettings() || false;
initScrollBarSync(scrollBarSettings);
Expand Down