Skip to content

Add include attribute for code fences #2797

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

Open
wants to merge 3 commits into
base: next
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
1 change: 1 addition & 0 deletions components/content/src/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ impl Page {
);
context.set_shortcode_definitions(shortcode_definitions);
context.set_current_page_path(&self.file.relative);
context.set_parent_absolute(&self.file.parent);
context.tera_context.insert("page", &SerializingPage::new(self, None, false));

let res = render_content(&self.raw_content, &context)
Expand Down
1 change: 1 addition & 0 deletions components/content/src/section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ impl Section {
);
context.set_shortcode_definitions(shortcode_definitions);
context.set_current_page_path(&self.file.relative);
context.set_parent_absolute(&self.file.parent);
context
.tera_context
.insert("section", &SerializingSection::new(self, SectionSerMode::ForMarkdown));
Expand Down
9 changes: 9 additions & 0 deletions components/markdown/src/codeblock/fence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub struct FenceSettings<'a> {
pub highlight_lines: Vec<RangeInclusive<usize>>,
pub hide_lines: Vec<RangeInclusive<usize>>,
pub name: Option<&'a str>,
pub include: Option<&'a str>,
pub enable_copy: bool,
}

Expand All @@ -37,6 +38,7 @@ impl<'a> FenceSettings<'a> {
highlight_lines: Vec::new(),
hide_lines: Vec::new(),
name: None,
include: None,
enable_copy: false,
};

Expand All @@ -48,6 +50,7 @@ impl<'a> FenceSettings<'a> {
FenceToken::HighlightLines(lines) => me.highlight_lines.extend(lines),
FenceToken::HideLines(lines) => me.hide_lines.extend(lines),
FenceToken::Name(n) => me.name = Some(n),
FenceToken::Include(file) => me.include = Some(file),
FenceToken::EnableCopy => me.enable_copy = true,
}
}
Expand All @@ -64,6 +67,7 @@ enum FenceToken<'a> {
HighlightLines(Vec<RangeInclusive<usize>>),
HideLines(Vec<RangeInclusive<usize>>),
Name(&'a str),
Include(&'a str),
EnableCopy,
}

Expand Down Expand Up @@ -116,6 +120,11 @@ impl<'a> Iterator for FenceIter<'a> {
return Some(FenceToken::Name(n));
}
}
"include" => {
if let Some(file) = tok_split.next() {
return Some(FenceToken::Include(file));
}
}
"copy" => return Some(FenceToken::EnableCopy),
lang => {
if tok_split.next().is_some() {
Expand Down
20 changes: 17 additions & 3 deletions components/markdown/src/codeblock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ mod fence;
mod highlight;

use std::ops::RangeInclusive;
use std::path::PathBuf;

use errors::{bail, Result};
use libs::syntect::util::LinesWithEndings;
use utils::fs::read_file;

use crate::codeblock::highlight::SyntaxHighlighter;
use config::highlighting::{resolve_syntax_and_theme, HighlightSource};
Expand Down Expand Up @@ -85,11 +87,12 @@ pub struct CodeBlock<'config> {
line_number_start: usize,
highlight_lines: Vec<RangeInclusive<usize>>,
hide_lines: Vec<RangeInclusive<usize>>,
include: Option<String>,
}

impl<'config> CodeBlock<'config> {
pub fn new<'fence_info>(
fence: FenceSettings<'fence_info>,
fence: &FenceSettings<'fence_info>,
config: &'config Config,
// path to the current file if there is one, to point where the error is
path: Option<&'config str>,
Expand Down Expand Up @@ -123,13 +126,24 @@ impl<'config> CodeBlock<'config> {
highlighter,
line_numbers: fence.line_numbers,
line_number_start: fence.line_number_start,
highlight_lines: fence.highlight_lines,
hide_lines: fence.hide_lines,
highlight_lines: fence.highlight_lines.clone(),
hide_lines: fence.hide_lines.clone(),
include: fence.include.map(|s| s.to_string()),
},
html_start,
))
}

pub fn include(&self, base: Option<&PathBuf>) -> Result<Option<String>> {
if let Some(base) = base {
let path = base.join(&self.include.as_ref().expect("No include path"));
let content = read_file(&path)?;
Ok(Some(content))
} else {
Ok(None)
}
}

pub fn highlight(&mut self, content: &str) -> String {
let mut buffer = String::new();
let mark_style = self.highlighter.mark_style();
Expand Down
9 changes: 9 additions & 0 deletions components/markdown/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::borrow::Cow;
use std::collections::HashMap;
use std::path::PathBuf;

use config::Config;
use libs::tera::{Context, Tera};
Expand All @@ -13,6 +14,7 @@ pub struct RenderContext<'a> {
pub config: &'a Config,
pub tera_context: Context,
pub current_page_path: Option<&'a str>,
pub parent_absolute: Option<&'a PathBuf>,
pub current_page_permalink: &'a str,
pub permalinks: Cow<'a, HashMap<String, String>>,
pub insert_anchor: InsertAnchor,
Expand Down Expand Up @@ -43,6 +45,7 @@ impl<'a> RenderContext<'a> {
config,
lang,
shortcode_definitions: Cow::Owned(HashMap::new()),
parent_absolute: None,
}
}

Expand All @@ -57,6 +60,11 @@ impl<'a> RenderContext<'a> {
self.current_page_path = Some(path);
}

/// Same as above
pub fn set_parent_absolute(&mut self, path: &'a PathBuf) {
self.parent_absolute = Some(path);
}

// In use in the markdown filter
// NOTE: This RenderContext is not i18n-aware, see MarkdownFilter::filter for details
// If this function is ever used outside of MarkdownFilter, take this into consideration
Expand All @@ -71,6 +79,7 @@ impl<'a> RenderContext<'a> {
config,
lang: &config.default_language,
shortcode_definitions: Cow::Owned(HashMap::new()),
parent_absolute: None,
}
}
}
24 changes: 21 additions & 3 deletions components/markdown/src/markdown.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::HashMap;
use std::fmt::Write;
use std::path::PathBuf;

use crate::markdown::cmark::CowStr;
use errors::bail;
Expand Down Expand Up @@ -564,7 +565,7 @@ pub fn markdown_to_html(
cmark::CodeBlockKind::Fenced(fence_info) => FenceSettings::new(fence_info),
_ => FenceSettings::new(""),
};
let (block, begin) = match CodeBlock::new(fence, context.config, path) {
let (block, begin) = match CodeBlock::new(&fence, context.config, path) {
Ok(cb) => cb,
Err(e) => {
error = Some(e);
Expand All @@ -576,8 +577,25 @@ pub fn markdown_to_html(
}
Event::End(TagEnd::CodeBlock { .. }) => {
if let Some(ref mut code_block) = code_block {
let html = code_block.highlight(&accumulated_block);
events.push(Event::Html(html.into()));
let maybe_inner = code_block.include(
context
.parent_absolute
.map(|e| path.map(|p| e.join(PathBuf::from(p).parent().unwrap())))
.flatten()
.as_ref(),
);
match maybe_inner {
Ok(i) => {
let inner = i.as_ref().unwrap_or(&accumulated_block);
let html = code_block.highlight(&inner);
events.push(Event::Html(html.into()));
}
Err(e) => {
error = Some(e);
break;
}
}

accumulated_block.clear();
}

Expand Down