Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Dan doc link fix#1281

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
chillenberger merged 7 commits intomasterfromdan-doc-link-fix
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes fromall 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
4 changes: 2 additions & 2 deletionspgml-dashboard/src/api/cms.rs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -557,7 +557,7 @@ This is the end of the markdown
#[sqlx::test]
async fn render_blogs_test() {
let client = Client::tracked(rocket().await).await.unwrap();
let blog: Collection = Collection::new("Blog", true);
let blog: Collection = Collection::new("Blog", true, HashMap::new());

for path in blog.index {
let req = client.get(path.clone().href);
Expand All@@ -579,7 +579,7 @@ This is the end of the markdown
#[sqlx::test]
async fn render_guides_test() {
let client = Client::tracked(rocket().await).await.unwrap();
let docs: Collection = Collection::new("Docs", true);
let docs: Collection = Collection::new("Docs", true, HashMap::new());

for path in docs.index {
let req = client.get(path.clone().href);
Expand Down
61 changes: 54 additions & 7 deletionspgml-dashboard/src/templates/docs.rs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
use convert_case;
use lazy_static::lazy_static;
use sailfish::TemplateOnce;
use serde::{Deserialize, Serialize};
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

use crate::utils::markdown::SearchResult;

Expand All@@ -11,6 +15,26 @@ pub struct Search {
pub results: Vec<SearchResult>,
}

lazy_static! {
static ref CMS_IDENTIFIER: CmsIdentifier = CmsIdentifier::new();
}

// Prevent css collisions in cms header ids.
pub struct CmsIdentifier {
pub id: String,
}

impl CmsIdentifier {
pub fn new() -> CmsIdentifier {
let mut s = DefaultHasher::new();
"cms header".hash(&mut s);

CmsIdentifier {
id: s.finish().to_string(),
}
}
}

/// Table of contents link.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TocLink {
Expand All@@ -25,9 +49,23 @@ impl TocLink {
/// # Arguments
///
/// * `title` - The title of the link.
/// * `counter` - The number of times that header is in the document
///
pub fn new(title: &str, counter: usize) -> TocLink {
let id = format!("header-{}", counter);
let conv = convert_case::Converter::new().to_case(convert_case::Case::Kebab);
let id = conv.convert(title.to_string());

// gitbook style id's
let id = format!(
"{}{}-{}",
id,
if counter > 0 {
format!("-{counter}")
} else {
String::new()
},
CMS_IDENTIFIER.id
);

TocLink {
title: title.to_string(),
Expand All@@ -43,11 +81,20 @@ impl TocLink {
self.level = level;
self
}
}

/// Table of contents template.
#[derive(TemplateOnce)]
#[template(path = "components/toc.html")]
pub struct Toc {
pub links: Vec<TocLink>,
/// Converts gitbook link fragment to toc header
pub fn from_fragment(link: String) -> TocLink {
match link.is_empty() {
true => TocLink {
title: String::new(),
id: String::new(),
level: 0,
},
_ => TocLink {
title: link.clone(),
id: format!("#{}-{}", link.clone(), CMS_IDENTIFIER.id),
level: 0,
},
}
}
}
112 changes: 55 additions & 57 deletionspgml-dashboard/src/utils/markdown.rs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,10 +3,7 @@ use crate::{templates::docs::TocLink, utils::config};
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};
use std::sync::{
atomic::{AtomicUsize, Ordering},
Arc,
};
use std::sync::Arc;

use anyhow::Result;
use comrak::{
Expand All@@ -15,25 +12,27 @@ use comrak::{
nodes::{Ast, AstNode, NodeValue},
parse_document, Arena, ComrakExtensionOptions, ComrakOptions, ComrakRenderOptions,
};
use convert_case;
use itertools::Itertools;
use regex::Regex;
use tantivy::collector::TopDocs;
use tantivy::query::{QueryParser, RegexQuery};
use tantivy::schema::*;
use tantivy::tokenizer::{LowerCaser, NgramTokenizer, TextAnalyzer};
use tantivy::{Index, IndexReader, SnippetGenerator};
use url::Url;

use std::sync::Mutex;

use std::fmt;

pub struct MarkdownHeadings {
counter: Arc<AtomicUsize>,
header_map: Arc<Mutex<HashMap<String, usize>>>,
}

impl Default for MarkdownHeadings {
fn default() -> Self {
Self {
counter: Arc::new(AtomicUsize::new(0)),
header_map: Arc::new(Mutex::new(HashMap::new())),
}
}
}
Expand All@@ -44,31 +43,42 @@ impl MarkdownHeadings {
}
}

/// Sets the document headers
///
/// uses toclink to ensure header id matches what the TOC expects
///
impl HeadingAdapter for MarkdownHeadings {
fn enter(&self, meta: &HeadingMeta) -> String {
// let id = meta.content.to_case(convert_case::Case::Kebab);
let id = self.counter.fetch_add(1, Ordering::SeqCst);
let id = format!("header-{}", id);
let conv = convert_case::Converter::new().to_case(convert_case::Case::Kebab);
let id = conv.convert(meta.content.to_string());

let index = match self.header_map.lock().unwrap().get(&id) {
Some(value) => value + 1,
_ => 0,
};
self.header_map.lock().unwrap().insert(id.clone(), index);

let id = TocLink::new(&id, index).id;

match meta.level {
1 => format!(r#"<h1 class="h1 mb-5" id="{id}">"#),
2 => format!(r#"<h2 class="h2 mb-4 mt-5" id="{id}">"#),
3 => format!(r#"<h3 class="h3 mb-4 mt-5" id="{id}">"#),
4 => format!(r#"<h4 class="h5 mb-3 mt-3" id="{id}">"#),
5 => format!(r#"<h5 class="h6 mb-2 mt-4" id="{id}">"#),
6 => format!(r#"<h6 class="h6 mb-1 mt-1" id="{id}">"#),
1 => format!(r##"<h1 class="h1 mb-5" id="{id}"><a href="#{id}">"##),
2 => format!(r##"<h2 class="h2 mb-4 mt-5" id="{id}"><a href="#{id}">"##),
3 => format!(r##"<h3 class="h3 mb-4 mt-5" id="{id}"><a href="#{id}">"##),
4 => format!(r##"<h4 class="h5 mb-3 mt-3" id="{id}"><a href="#{id}">"##),
5 => format!(r##"<h5 class="h6 mb-2 mt-4" id="{id}"><a href="#{id}">"##),
6 => format!(r##"<h6 class="h6 mb-1 mt-1" id="{id}"><a href="#{id}">"##),
_ => unreachable!(),
}
}

fn exit(&self, meta: &HeadingMeta) -> String {
match meta.level {
1 => r#"</h1>"#,
2 => r#"</h2>"#,
3 => r#"</h3>"#,
4 => r#"</h4>"#,
5 => r#"</h5>"#,
6 => r#"</h6>"#,
1 => r#"</a></h1>"#,
2 => r#"</a></h2>"#,
3 => r#"</a></h3>"#,
4 => r#"</a></h4>"#,
5 => r#"</a></h5>"#,
6 => r#"</a></h6>"#,
_ => unreachable!(),
}
.into()
Expand DownExpand Up@@ -335,38 +345,6 @@ where
Ok(())
}

pub fn nest_relative_links(node: &mut markdown::mdast::Node, path: &PathBuf) {
let _ = iter_mut_all(node, &mut |node| {
if let markdown::mdast::Node::Link(ref mut link) = node {
match Url::parse(&link.url) {
Ok(url) => {
if !url.has_host() {
let mut url_path = url.path().to_string();
let url_path_path = Path::new(&url_path);
match url_path_path.extension() {
Some(ext) => {
if ext.to_str() == Some(".md") {
let base = url_path_path.with_extension("");
url_path = base.into_os_string().into_string().unwrap();
}
}
_ => {
warn!("not markdown path: {:?}", path)
}
}
link.url = path.join(url_path).into_os_string().into_string().unwrap();
}
}
Err(e) => {
warn!("could not parse url in markdown: {}", e)
}
}
}

Ok(())
});
}

/// Get the title of the article.
///
/// # Arguments
Expand DownExpand Up@@ -462,11 +440,10 @@ pub fn wrap_tables<'a>(root: &'a AstNode<'a>, arena: &'a Arena<AstNode<'a>>) ->
///
pub fn get_toc<'a>(root: &'a AstNode<'a>) -> anyhow::Result<Vec<TocLink>> {
let mut links = Vec::new();
let mutheader_counter = 0;
let mutheader_count: HashMap<String, usize> = HashMap::new();

iter_nodes(root, &mut |node| {
if let NodeValue::Heading(header) = &node.data.borrow().value {
header_counter += 1;
if header.level != 1 {
let sibling = match node.first_child() {
Some(child) => child,
Expand All@@ -476,7 +453,14 @@ pub fn get_toc<'a>(root: &'a AstNode<'a>) -> anyhow::Result<Vec<TocLink>> {
}
};
if let NodeValue::Text(text) = &sibling.data.borrow().value {
links.push(TocLink::new(text, header_counter - 1).level(header.level));
let index = match header_count.get(text) {
Some(index) => index + 1,
_ => 0,
};

header_count.insert(text.clone(), index);

links.push(TocLink::new(text, index).level(header.level));
return Ok(false);
}
}
Expand DownExpand Up@@ -753,11 +737,25 @@ pub fn mkdocs<'a>(root: &'a AstNode<'a>, arena: &'a Arena<AstNode<'a>>) -> anyho
let path = Path::new(link.url.as_str());

if path.is_relative() {
let fragment = match link.url.find("#") {
Some(index) => link.url[index + 1..link.url.len()].to_string(),
_ => "".to_string(),
};

for _ in 0..fragment.len() + 1 {
link.url.pop();
}

if link.url.ends_with(".md") {
for _ in 0..".md".len() {
link.url.pop();
}
}

let header_id = TocLink::from_fragment(fragment).id;
for c in header_id.chars() {
link.url.push(c)
}
}

Ok(true)
Expand Down
16 changes: 16 additions & 0 deletionspgml-dashboard/static/css/scss/pages/_docs.scss
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -206,5 +206,21 @@
display: contents !important;
}
}

h1, h2, h3, h4, h5, h6 {
scroll-margin-top: 108px;

&:hover {
&:after {
content: '#';
margin-left: 0.2em;
position: absolute;
}
}

a {
color: inherit !important;
}
}
}

12 changes: 12 additions & 0 deletionspgml-dashboard/static/js/docs-toc.js
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,4 +15,16 @@ export default class extends Controller {
threshold: [1],
})
}

setUrlFragment(e) {
let href = e.target.attributes.href.nodeValue;
if (href) {
if (href.startsWith("#")) {
let hash = href.slice(1);
if (window.location.hash != hash) {
window.location.hash = hash
}
}
}
}
}
18 changes: 0 additions & 18 deletionspgml-dashboard/templates/components/toc.html
View file
Open in desktop

This file was deleted.

2 changes: 1 addition & 1 deletionpgml-dashboard/templates/layout/nav/toc.html
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ <h6 class="mb-2 pb-2 d-none d-xxl-block">Table of Contents</h6>
<div id="toc-nav" class="d-xxl-flex pt-2 flex-column collapse border-top" aria-orientation="vertical" data-controller="docs-toc">
<% for link in toc_links.iter() { %>
<div style="padding-left: <%= link.level as f32 * 0.7 - 1.4 %>rem;">
<a class="nav-link px-0 text-break" href="#<%= link.id %>" role="button" data-action="docs-toc#scrollSpyAppend">
<a class="nav-link px-0 text-break" href="#<%= link.id %>" role="button" data-action="click->docs-toc#setUrlFragment">
<%= link.title %>
</a>
</div>
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp