Skip to content

Commit

Permalink
Merge pull request #10 from revolter/feature/markdown-text-formatting
Browse files Browse the repository at this point in the history
Added support for Markdown text formatting
  • Loading branch information
revolter authored Jun 18, 2024
2 parents 12aa5c7 + b8ebe45 commit d1e418c
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 46 deletions.
132 changes: 114 additions & 18 deletions _sass/minima/custom-styles.scss
Original file line number Diff line number Diff line change
@@ -1,26 +1,122 @@
html, body {
height: 100%;
}
$default-spacing: 8px;

.page-content {
display: flex;
}
$lm-button-background-color: #f0f0f0;
$lm-button-hover-background-color: #e1e1e1;

$dm-button-background-color: #333333;
$dm-button-hover-background-color: #444444;

$button-background-color: $lm-button-background-color;
$button-hover-background-color: $lm-button-hover-background-color;

@if $color-scheme-auto {
:root {
--io-button-background-color: #{$lm-button-background-color};
--io-button-hover-background-color: #{$lm-button-hover-background-color};
}

@media (prefers-color-scheme: dark) {
:root {
--io-button-background-color: #{$dm-button-background-color};
--io-button-hover-background-color: #{$dm-button-hover-background-color};
}
}

.page-content > .wrapper, .home {
display: flex;
flex-grow: 1;
$button-background-color: var(--io-button-background-color);
$button-hover-background-color: var(--io-button-hover-background-color);
} @else if $color-scheme-dark {
$button-background-color: $dm-button-background-color;
$button-hover-background-color: $dm-button-hover-background-color;
}

.page-content > .wrapper {
justify-content: center;
html {
height: 100%;
}

textarea {
color: $text-color;
background-color: $code-background-color;
border-color: $border-color-01;
@include relative-font-size(1);
body {
height: 100%;

code {
text-wrap-mode: wrap;
word-wrap: anywhere;
}

.page-content {
display: flex;

.wrapper {
display: flex;
flex-grow: 1;
justify-content: center;

.home {
display: flex;
flex-grow: 1;
flex-direction: column;
gap: $default-spacing;

.toolbar {
display: flex;
justify-content: flex-end;

button {
@include relative-font-size(1);
color: $text-color;
background: $button-background-color;
border-style: solid;
border-width: 1px;
border-color: $border-color-01;
border-radius: 6px;
cursor: pointer;

transition: background 150ms linear;
&:hover {
background: $button-hover-background-color;
}

}
}

.content {
@media screen and (min-width: $on-laptop) {
flex-direction: row;
}

@media not screen and (min-width: $on-laptop) {
flex-direction: column;
}

display: flex;
flex-grow: 1;
justify-content: center;

gap: $default-spacing;

textarea {
color: $text-color;
@include relative-font-size(1);
}

.markdown-preview {
border-style: solid;
border-width: 1px;

@media not screen and (min-width: $on-laptop) {
overflow: auto;
}
}

textarea, .markdown-preview {
flex-grow: 1;
flex-basis: 0;

background-color: $code-background-color;
border-color: $border-color-01;

width: 100%;
padding: 8px;
padding: $default-spacing;
}
}
}
}
}
}
122 changes: 97 additions & 25 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
layout: home
---

<script src="{{ 'pako/dist/pako.js' | node_module_url | relative_url }}"></script>
<script src="{{ 'js-base64/base64.js' | node_module_url | relative_url }}"></script>
<script src="{{ 'pako/dist/pako.min.js' | node_module_url | relative_url }}"></script>
<script src="{{ 'showdown/dist/showdown.min.js' | node_module_url | relative_url }}"></script>

{%- assign markdown_preview_id = 'markdown-preview' -%}
{%- capture toggle_markdown_preview_id -%}toggle-{{ markdown_preview_id }}{%- endcapture -%}

{%- assign textarea_id = 'textarea' -%}
{%- capture textarea_placeholder -%}
Expand All @@ -25,7 +29,14 @@

{%- endcapture -%}

<textarea id="{{ textarea_id }}" placeholder="{{ textarea_placeholder }}" autofocus></textarea>
<div class="toolbar">
<button id="{{ toggle_markdown_preview_id }}">Toggle Markdown preview</button>
</div>

<div class="content">
<textarea id="{{ textarea_id }}" placeholder="{{ textarea_placeholder }}" autofocus></textarea>
<div id="{{ markdown_preview_id }}" class="markdown-preview"></div>
</div>

<script>
function main() {
Expand All @@ -37,18 +48,50 @@
}

function run() {
const toggleMarkdownPreview = document.getElementById('{{ toggle_markdown_preview_id }}');
const textarea = document.getElementById('{{ textarea_id }}');
loadValue(textarea);
const markdownPreview = document.getElementById('{{ markdown_preview_id }}');

loadMarkdownPreviewVisibility(markdownPreview);
addClickListener(toggleMarkdownPreview);

loadValue(textarea, markdownPreview);
addValueListener(textarea);
addFocusListener(textarea);
addHashListener(textarea);
addHashListener(textarea, markdownPreview);
}

function addClickListener(toggleMarkdownPreview) {
toggleMarkdownPreview.addEventListener('click', () => {
const searchParams = new URLSearchParams(window.location.search);
if (isMarkdownPreviewEnabled()) {
searchParams.delete('{{ markdown_preview_id }}');
} else {
searchParams.set('{{ markdown_preview_id }}', 'true');
}
document.location.search = searchParams.toString();
}, false);
}

function loadMarkdownPreviewVisibility(markdownPreview) {
if (isMarkdownPreviewEnabled()) {
markdownPreview.style.display = 'block';
} else {
markdownPreview.style.display = 'none';
}
}

function isMarkdownPreviewEnabled() {
const searchParams = new URLSearchParams(window.location.search);
return searchParams.has('{{ markdown_preview_id }}');
}

function loadValue(textarea) {
function loadValue(textarea, markdownPreview) {
const value = retrieveValue();
const oldValue = textarea.value;
textarea.value = value;
updateTitle(value);
updateMarkdownPreviewIfNeeded(value, markdownPreview);
updateTitle(value, markdownPreview.textContent);
if (oldValue === '') {
textarea.selectionStart = value.length;
}
Expand All @@ -66,26 +109,23 @@

function addValueListener(textarea) {
textarea.addEventListener('input', debounce((event) => {
const value = event.target.value;
onValueUpdate(value);
storeValue(event.target.value);
}, 300), false);
}

function addFocusListener(textarea) {
textarea.addEventListener('blur', () => {
const value = textarea.value;
onValueUpdate(value);
storeValue(textarea.value);
}, false);

window.addEventListener('blur', () => {
const value = textarea.value;
onValueUpdate(value);
storeValue(textarea.value);
}, false);
}

function addHashListener(textarea) {
function addHashListener(textarea, markdownPreview) {
window.addEventListener('hashchange', () => {
loadValue(textarea);
loadValue(textarea, markdownPreview);
});
}

Expand All @@ -95,22 +135,54 @@
return deserialize(hash.substring(1));
}

function onValueUpdate(value) {
storeValue(value);
updateTitle(value);
}

function storeValue(value) {
window.location.hash = '#' + serialize(value);
}

function updateTitle(value) {
document.title = '{{ site.tagline }}';
function updateTitle(value, markdownValue) {
const finalValue = markdownValue || value;

const titleParts = [];
const customParts = [];

const rawTitle = finalValue.split('\n', 1)[0];
if (rawTitle !== '') {
const truncatedTitle = truncate(rawTitle.trim(), 30);
customParts.push(truncatedTitle);
}

if (isMarkdownPreviewEnabled()) {
customParts.push('Markdown');
}

if (customParts.length > 0) {
titleParts.push(customParts.join(' - '));
}
titleParts.push('{{ site.tagline }}');

const rawTitle = value.split('\n', 1)[0];
if (rawTitle === '') { return; }
const truncatedTitle = truncate(rawTitle.trim(), 30);
document.title = truncatedTitle + ' | ' + document.title;
document.title = titleParts.join(' | ');
}

function updateMarkdownPreviewIfNeeded(value, markdownPreview) {
if (!isMarkdownPreviewEnabled()) { return; }

const converter = new showdown.Converter({
omitExtraWLInCodeBlocks: true,
noHeaderId: true,
parseImgDimensions: true,
simplifiedAutoLink: true,
literalMidWordUnderscores: true,
strikethrough: true,
tables: true,
tasklists: true,
smoothLivePreview: true,
simpleLineBreaks: true,
openLinksInNewWindow: true,
emoji: true,
splitAdjacentBlockquotes: true
});
const html = converter.makeHtml(value);
markdownPreview.innerHTML = html;
}

function truncate(string, limit) {
Expand Down
19 changes: 17 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
},
"dependencies": {
"js-base64": "*",
"pako": "*"
"pako": "*",
"showdown": "*"
},
"devDependencies": {
"watchy": "*"
Expand Down

0 comments on commit d1e418c

Please sign in to comment.