asciidork_parser/tasks/
attr_refs.rs1use crate::internal::*;
2
3pub trait AttrRefObserver {
4 fn attr_ref_replaced(&self, attr_name: &str, loc: SourceLocation);
5 fn attr_ref_missing(&self, attr_name: &str, loc: SourceLocation);
6}
7
8impl<'arena> Parser<'arena> {
9 pub(crate) fn set_source_file_attrs(&mut self) {
10 let source_file = self.lexer.source_file().clone();
11 match source_file {
12 SourceFile::Stdin { .. } => {}
13 SourceFile::Path(path) => {
14 let file_stem = path.file_stem();
15 let ext = path.extension();
16 self.insert_file_attr("docfilesuffix", ext.to_string());
17 self.insert_file_attr("docname", file_stem.to_string());
18 self.insert_file_attr("asciidork-docfilename", format!("{}{}", file_stem, ext));
19 match self.document.meta.safe_mode {
20 SafeMode::Server | SafeMode::Secure => {
21 self.insert_file_attr("docdir", "");
22 self.insert_file_attr("docfile", "");
23 }
24 SafeMode::Safe | SafeMode::Unsafe => {
25 self.insert_file_attr("docfile", path.to_string());
26 self.insert_file_attr("docdir", path.dirname().to_string());
27 }
28 }
29 }
30 SourceFile::Tmp => {}
31 };
32 }
33
34 pub(crate) fn push_token_replacing_attr_ref(
35 &mut self,
36 mut token: Token<'arena>,
37 line: &mut Line<'arena>,
38 drop_line: &mut bool,
39 ) -> Result<()> {
40 if token.kind(TokenKind::AttrRef) && self.ctx.subs.attr_refs() {
41 match self.document.meta.get(token.attr_name()) {
42 Some(AttrValue::String(attr_val)) => {
43 #[cfg(feature = "attr_ref_observation")]
44 if let Some(observer) = &self.attr_ref_observer {
45 observer.attr_ref_replaced(token.attr_name(), token.loc);
46 }
47 if !attr_val.is_empty() {
48 self.lexer.set_tmp_buf(attr_val, BufLoc::Repeat(token.loc));
49 }
50 line.push(token);
51 }
52 _ => {
53 #[cfg(feature = "attr_ref_observation")]
54 if let Some(observer) = &self.attr_ref_observer {
55 observer.attr_ref_missing(token.attr_name(), token.loc);
56 }
57 match self.document.meta.str("attribute-missing") {
58 Some("drop") => {}
59 Some("drop-line") => *drop_line = true,
60 val => {
61 token.kind = TokenKind::Word;
62 if val == Some("warn") {
63 self.err_token_full("Skipping reference to missing attribute", &token)?;
64 }
65 line.push(token);
66 }
67 }
68 }
69 }
70 } else {
71 line.push(token);
72 }
73 Ok(())
74 }
75
76 fn insert_file_attr(&mut self, key: &str, value: impl Into<AttrValue>) {
77 self
78 .document
79 .meta
80 .insert_job_attr(key, JobAttr::readonly(value))
81 .unwrap();
82 }
83
84 pub(crate) fn insert_doc_attr(
85 &mut self,
86 key: &str,
87 value: impl Into<AttrValue>,
88 ) -> std::result::Result<(), String> {
89 self.document.meta.insert_doc_attr(key, value)
90 }
91}