Code highlighting
This commit is contained in:
parent
a9ef5c8f93
commit
4305da1d0c
@ -27,6 +27,16 @@ similis: caput te prodere disceditis: quinque: an et in, accipis divitior talia?
|
|||||||
Per deducit ademi, _sub_ qvem orbatura Pindo te manus verbaque **tuorum nati**
|
Per deducit ademi, _sub_ qvem orbatura Pindo te manus verbaque **tuorum nati**
|
||||||
vivere, an me detectique est. Decoram erat mediaque auras.
|
vivere, an me detectique est. Decoram erat mediaque auras.
|
||||||
|
|
||||||
|
`sh ./oneliner.sh`
|
||||||
|
|
||||||
|
This is a paragraph with a `reference to code` inside.
|
||||||
|
This is a paragraph with a `reference to code` inside.
|
||||||
|
This is a paragraph with a `reference to code` inside.
|
||||||
|
This is a paragraph with a `reference to code` inside.
|
||||||
|
This is a paragraph with a `reference to code` inside.
|
||||||
|
This is a paragraph with a `reference to code` inside.
|
||||||
|
This is a paragraph with a `reference to code` inside.
|
||||||
|
|
||||||
> Leti ensis mihi torquere fiducia me sunt nec prima caeli quaeras et coma
|
> Leti ensis mihi torquere fiducia me sunt nec prima caeli quaeras et coma
|
||||||
> tinctis sibi; tua fidem aethera. Animosque ferret vultus puellari poteris
|
> tinctis sibi; tua fidem aethera. Animosque ferret vultus puellari poteris
|
||||||
> florilegae ignes crevisse ad pulvere recenti, luce male; neque nec!
|
> florilegae ignes crevisse ad pulvere recenti, luce male; neque nec!
|
||||||
@ -51,7 +61,7 @@ praemia pariter exaestuat fecerat. Haemonio quem: _in_ sibi spectans parmam,
|
|||||||
tetenderat filia ait quo calcitrat at vides, cui iuvenem rerum erat. Eminus
|
tetenderat filia ait quo calcitrat at vides, cui iuvenem rerum erat. Eminus
|
||||||
flammas iamque.
|
flammas iamque.
|
||||||
|
|
||||||
```typescript
|
```ts
|
||||||
var brouterVisualRecycle =
|
var brouterVisualRecycle =
|
||||||
netmaskExbibyteMac +
|
netmaskExbibyteMac +
|
||||||
download(twitter_serp_yobibyte, backlinkDirectBandwidth, hot)
|
download(twitter_serp_yobibyte, backlinkDirectBandwidth, hot)
|
||||||
@ -73,7 +83,7 @@ Erat Iunonis pennis lugubris, vixque nec quo tua lacrimarum nubila nobiscum.
|
|||||||
Ferrum inhaeret ille; operi in Theseus contingere fateri, mirabatur, consequar
|
Ferrum inhaeret ille; operi in Theseus contingere fateri, mirabatur, consequar
|
||||||
ullis, exuit fatemur humani iustis!
|
ullis, exuit fatemur humani iustis!
|
||||||
|
|
||||||
```
|
```js
|
||||||
var mpeg_reader_modifier = jfs;
|
var mpeg_reader_modifier = jfs;
|
||||||
if (318464 >= association_thunderbolt_bar) {
|
if (318464 >= association_thunderbolt_bar) {
|
||||||
copyrightMemoryWep.skinHeaderEmoticon =
|
copyrightMemoryWep.skinHeaderEmoticon =
|
||||||
|
@ -23,6 +23,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|||||||
image = "0.25.2"
|
image = "0.25.2"
|
||||||
anyhow = "1.0.86"
|
anyhow = "1.0.86"
|
||||||
rayon = "1.10.0"
|
rayon = "1.10.0"
|
||||||
|
syntect = "5.2.0"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
rustflags = ["-Z", "threads=8"]
|
rustflags = ["-Z", "threads=8"]
|
||||||
|
@ -48,9 +48,6 @@ async fn main() {
|
|||||||
axum::serve(listener, app).await.unwrap();
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Display blog posts
|
|
||||||
// TODO Markdown notes
|
|
||||||
// TODO code snippets highlighting
|
|
||||||
// TODO responsive design
|
// TODO responsive design
|
||||||
// TODO Colors
|
// TODO Colors
|
||||||
// TODO go live pipeline
|
// TODO go live pipeline
|
||||||
|
@ -4,8 +4,9 @@ use axum::http::StatusCode;
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use gray_matter::{engine::YAML, Matter};
|
use gray_matter::{engine::YAML, Matter};
|
||||||
use image::image_dimensions;
|
use image::image_dimensions;
|
||||||
use pulldown_cmark::{Event, Options, Parser, Tag, TagEnd};
|
use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag, TagEnd};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Deserializer};
|
use serde::{de::DeserializeOwned, Deserialize, Deserializer};
|
||||||
|
use syntect::{highlighting::ThemeSet, html::highlighted_html_for_string, parsing::SyntaxSet};
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
@ -68,6 +69,11 @@ pub async fn parse_post<'de, Metadata: DeserializeOwned>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TextKind {
|
||||||
|
Text,
|
||||||
|
Code(String),
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_html(markdown: &str, generate_images: bool) -> String {
|
pub fn parse_html(markdown: &str, generate_images: bool) -> String {
|
||||||
let mut options = Options::empty();
|
let mut options = Options::empty();
|
||||||
options.insert(Options::ENABLE_TABLES);
|
options.insert(Options::ENABLE_TABLES);
|
||||||
@ -77,6 +83,11 @@ pub fn parse_html(markdown: &str, generate_images: bool) -> String {
|
|||||||
options.insert(Options::ENABLE_SMART_PUNCTUATION);
|
options.insert(Options::ENABLE_SMART_PUNCTUATION);
|
||||||
options.insert(Options::ENABLE_HEADING_ATTRIBUTES);
|
options.insert(Options::ENABLE_HEADING_ATTRIBUTES);
|
||||||
|
|
||||||
|
let mut text_kind = TextKind::Text;
|
||||||
|
let syntax_set = SyntaxSet::load_defaults_newlines();
|
||||||
|
let theme_set = ThemeSet::load_defaults();
|
||||||
|
let theme = theme_set.themes.get("InspiredGitHub").unwrap();
|
||||||
|
|
||||||
let parser = Parser::new_ext(markdown, options).map(|event| match event {
|
let parser = Parser::new_ext(markdown, options).map(|event| match event {
|
||||||
/*
|
/*
|
||||||
Parsing images considers `alt` attribute as inner `Text` event
|
Parsing images considers `alt` attribute as inner `Text` event
|
||||||
@ -123,16 +134,6 @@ pub fn parse_html(markdown: &str, generate_images: bool) -> String {
|
|||||||
alt = title,
|
alt = title,
|
||||||
src = dest_url,
|
src = dest_url,
|
||||||
));
|
));
|
||||||
// let picture_markup = format!(
|
|
||||||
// r#"
|
|
||||||
// <img
|
|
||||||
// alt="{alt}"
|
|
||||||
// src="{src}"
|
|
||||||
// />"#,
|
|
||||||
// alt = title,
|
|
||||||
// src = dest_url,
|
|
||||||
// );
|
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"Image link_type: {:?} url: {} title: {} id: {}",
|
"Image link_type: {:?} url: {} title: {} id: {}",
|
||||||
link_type, dest_url, title, id
|
link_type, dest_url, title, id
|
||||||
@ -147,8 +148,37 @@ pub fn parse_html(markdown: &str, generate_images: bool) -> String {
|
|||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(lang))) => {
|
||||||
|
text_kind = TextKind::Code(lang.to_string());
|
||||||
|
Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(lang)))
|
||||||
|
}
|
||||||
|
Event::Text(text) => match &text_kind {
|
||||||
|
TextKind::Code(lang) => {
|
||||||
|
// TODO Check https://github.com/trishume/syntect/pull/535 for typescript support
|
||||||
|
let lang = if ["ts".to_string(), "typescript".to_string()].contains(lang) {
|
||||||
|
"javascript"
|
||||||
|
} else {
|
||||||
|
lang
|
||||||
|
};
|
||||||
|
let syntax_reference = syntax_set
|
||||||
|
.find_syntax_by_token(lang)
|
||||||
|
.unwrap_or(syntax_set.find_syntax_plain_text());
|
||||||
|
syntax_set.syntaxes().iter().for_each(|sr| {
|
||||||
|
debug!("{}", sr.name);
|
||||||
|
});
|
||||||
|
let highlighted =
|
||||||
|
highlighted_html_for_string(&text, &syntax_set, syntax_reference, theme)
|
||||||
|
.unwrap();
|
||||||
|
Event::Html(highlighted.into())
|
||||||
|
}
|
||||||
|
_ => Event::Text(text),
|
||||||
|
},
|
||||||
Event::Start(_) => event,
|
Event::Start(_) => event,
|
||||||
Event::End(TagEnd::Image) => Event::Html("</figcaption></figure>".into()),
|
Event::End(TagEnd::Image) => Event::Html("</figcaption></figure>".into()),
|
||||||
|
Event::End(TagEnd::CodeBlock) => {
|
||||||
|
text_kind = TextKind::Text;
|
||||||
|
Event::End(TagEnd::CodeBlock)
|
||||||
|
}
|
||||||
_ => event,
|
_ => event,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ a {
|
|||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
@apply text-sm mx-auto max-w-image table-auto border-collapse border-spacing-12 border border-gray-200 rounded md:text-base md:my-4 lg:text-xl lg:my-8;
|
@apply text-sm mx-auto my-4 max-w-image table-auto border-collapse border-spacing-12 border border-gray-200 rounded md:text-base lg:text-xl lg:my-8;
|
||||||
}
|
}
|
||||||
|
|
||||||
thead {
|
thead {
|
||||||
@ -62,6 +62,14 @@ a {
|
|||||||
@apply my-2 md:my-4 text-slate-600 max-w-note;
|
@apply my-2 md:my-4 text-slate-600 max-w-note;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:not(pre) code {
|
||||||
|
@apply text-pink-950 rounded border border-blue-300 px-1 py-0.5 bg-blue-100 text-sm md:text-base lg:text-xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code pre {
|
||||||
|
@apply mx-2 rounded lg:mx-auto lg:text-lg shadow-sm lg:max-w-note;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-embed {
|
.video-embed {
|
||||||
|
@ -1228,6 +1228,10 @@ a {
|
|||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
table {
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
table {
|
table {
|
||||||
max-width: 70rem;
|
max-width: 70rem;
|
||||||
}
|
}
|
||||||
@ -1256,12 +1260,6 @@ a {
|
|||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
line-height: 1.25rem;
|
line-height: 1.25rem;
|
||||||
}
|
}
|
||||||
@media (min-width: 768px) {
|
|
||||||
table {
|
|
||||||
margin-top: 1rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
table {
|
table {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
@ -1371,6 +1369,77 @@ a {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
:not(pre) code {
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
}
|
||||||
|
:not(pre) code {
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
:not(pre) code {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(147 197 253 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
:not(pre) code {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(219 234 254 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
:not(pre) code {
|
||||||
|
padding-left: 0.25rem;
|
||||||
|
padding-right: 0.25rem;
|
||||||
|
}
|
||||||
|
:not(pre) code {
|
||||||
|
padding-top: 0.125rem;
|
||||||
|
padding-bottom: 0.125rem;
|
||||||
|
}
|
||||||
|
:not(pre) code {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
}
|
||||||
|
:not(pre) code {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(80 7 36 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
:not(pre) code {
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
:not(pre) code {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 1.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pre code pre {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
pre code pre {
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
}
|
||||||
|
pre code pre {
|
||||||
|
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||||
|
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
pre code pre {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
pre code pre {
|
||||||
|
max-width: 60rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
pre code pre {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
line-height: 1.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-embed {
|
.video-embed {
|
||||||
|
Loading…
Reference in New Issue
Block a user