Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make links clickable #85

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
16 changes: 16 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ rusqlite_migration = { version = "1", default-features = false }
rust-argon2 = "2.0.0"
sha2 = "0"
serde = { version = "1", features = ["derive"] }
syntect = { version = "5", default-features = false, features = ["html", "plist-load", "regex-fancy"] }
syntect = { version = "5", default-features = false, features = ["html", "plist-load", "regex-fancy", "yaml-load"] }
thiserror = "2"
time = { version = "0.3", features = ["macros", "serde"] }
tokio = { version = "1", features = ["full"] }
Expand Down
33 changes: 33 additions & 0 deletions assets/LinkHighlight.sublime-syntax
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: LinkHighlight
file_extensions:
- link_highlight
scope: text.highlighting
contexts:
main:
- match: (<)((?:https?|ftp)://.*?)(>)
scope: meta.link.inet.markdown
captures:
1: punctuation.definition.link.begin.markdown
2: markup.underline.link.markdown
3: punctuation.definition.link.end.markdown
- match: (((https|http|ftp)://)|www\.)[\w-]+(\.[\w-]+)+
scope: markup.underline.link.markdown
push: # After a valid domain, zero or more non-space non-< characters may follow
- match: (?=[?!.,:*_~]*[\s<]) # Trailing punctuation (specifically, ?, !, ., ,, :, *, _, and ~) will not be considered part of the autolink, though they may be included in the interior of the link
pop: true
- match: (?={{html_entity}}[?!.,:*_~]*[\s<]) # If an autolink ends in a semicolon (;), we check to see if it appears to resemble an entity reference; if the preceding text is & followed by one or more alphanumeric characters. If so, it is excluded from the autolink
pop: true
- match: \( # When an autolink ends in ), we scan the entire autolink for the total number of parentheses. If there is a greater number of closing parentheses than opening ones, we don’t consider the last character part of the autolink, in order to facilitate including an autolink inside a parenthesis
push:
- meta_scope: markup.underline.link.markdown
- match: (?=[?!.,:*_~]*[\s<])
pop: true
- match: \)
pop: true
- match: (?=\)[?!.,:*_~]*[\s<])
pop: true
- match: '[^?!.,:*_~\s<&()]+|\S'
scope: markup.underline.link.markdown
21 changes: 14 additions & 7 deletions src/highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::io::Cursor;
use std::sync::LazyLock;
use syntect::highlighting::ThemeSet;
use syntect::html::{css_for_theme_with_class_style, line_tokens_to_classed_spans, ClassStyle};
use syntect::parsing::{ParseState, ScopeStack, SyntaxReference, SyntaxSet};
use syntect::parsing::{ParseState, ScopeStack, SyntaxDefinition, SyntaxReference, SyntaxSet};
use syntect::util::LinesWithEndings;

const HIGHLIGHT_LINE_LENGTH_CUTOFF: usize = 2048;
Expand All @@ -32,6 +32,11 @@ pub static DATA: LazyLock<Data> = LazyLock::new(|| {
let dark = Css::new("dark", &DARK_CSS);
let syntax_set: SyntaxSet =
syntect::dumps::from_binary(include_bytes!("../assets/newlines.packdump"));
let link_highlighting = SyntaxDefinition::load_from_str(
include_str!("../assets/LinkHighlight.sublime-syntax"), false, None).expect("loading link style");
let mut builder = syntax_set.into_builder();
builder.add(link_highlighting);
let syntax_set = builder.build();
Comment on lines +35 to +39
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kills debug performance. We could use the trick from https://stackoverflow.com/questions/60751806/how-to-compile-some-dependencies-with-release but I don't know which dependency is the culprit.

Copy link
Contributor Author

@FliegendeWurst FliegendeWurst Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And it depends on yaml-rust which was promptly denied by CI :(

trishume/syntect#537

let mut syntaxes = syntax_set.syntaxes().to_vec();
syntaxes.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap_or(Ordering::Less));

Expand Down Expand Up @@ -72,12 +77,13 @@ impl<'a> Css<'a> {
}

fn highlight(source: &str, ext: &str) -> Result<String, Error> {
let syntax_ref = DATA
.syntax_set
.find_syntax_by_extension(ext)
let syntax_ref = (ext != "txt").then(||
DATA
.syntax_set
.find_syntax_by_extension(ext)).flatten()
.unwrap_or_else(|| {
DATA.syntax_set
.find_syntax_by_extension("txt")
.find_syntax_by_extension("link_highlight")
.expect("finding txt syntax")
});

Expand All @@ -86,12 +92,13 @@ fn highlight(source: &str, ext: &str) -> Result<String, Error> {
let mut scope_stack = ScopeStack::new();

for (mut line_number, line) in LinesWithEndings::from(source).enumerate() {
// let mut links = HashMap::new();
let (formatted, delta) = if line.len() > HIGHLIGHT_LINE_LENGTH_CUTOFF {
(line.to_string(), 0)
} else {
let parsed = parse_state.parse_line(line, &DATA.syntax_set)?;
let parsed = parse_state.parse_line(&line, &DATA.syntax_set)?;
line_tokens_to_classed_spans(
line,
&line,
parsed.as_slice(),
ClassStyle::Spaced,
&mut scope_stack,
Expand Down
10 changes: 10 additions & 0 deletions src/themes/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,16 @@ td.line-number {
user-select: text;
}

.line a {
color: rgba(57, 186, 230, .7);
}
FliegendeWurst marked this conversation as resolved.
Show resolved Hide resolved
.line a:hover {
text-decoration: underline;
}
.line a:visited {
color: rgba(225, 57, 230, 0.7);
}

.center {
position: absolute;
left: 50%;
Expand Down
1 change: 1 addition & 0 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
</header>
<main>
{% block content %}{% endblock %}
{% block content_post %}{% endblock %}
</main>
</div>
</body>
Expand Down
23 changes: 23 additions & 0 deletions templates/paste.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,26 @@
<li><a href="{{ base_path.join(id) }}?fmt=raw"><button>raw</button></a></li>
<li><a href="{{ base_path.join(id) }}?fmt=qr"><button>qr</button></a></li>
{% endblock %}

{% block content_post %}
<script>
while (true) {
const o = document.querySelector("span.link");
if (!o) {
break;
}
let l = o.nextSibling;
let link = o.innerHTML;
while(l != null && l.tagName == "SPAN" && l.classList.contains("link")) {
let prevL = l;
l = l.nextSibling;
link += prevL.innerText;
prevL.remove();
}
o.setAttribute("href", link);
o.innerText = link;
o.className = "";
o.outerHTML = o.outerHTML.replace(/^<span(.*)span>$/, "<a$1a>");
}
</script>
{% endblock %}
Loading