Update docs
This commit is contained in:
parent
b5c8fbbfea
commit
cf3491e5a7
12 changed files with 184 additions and 36 deletions
6
docs/external/graphviz.nml
vendored
6
docs/external/graphviz.nml
vendored
|
@ -35,6 +35,10 @@ digraph {
|
||||||
[/graph]
|
[/graph]
|
||||||
#+LAYOUT_END
|
#+LAYOUT_END
|
||||||
|
|
||||||
|
The Graphviz functionnality requires the `dot` executable. More information on [Graphviz's website](file:///home/baraquiel/Programming/nml_rs/out/Graphviz.html).
|
||||||
|
|
||||||
|
# Synopsis
|
||||||
|
|
||||||
Graphs blocks are delimited by `` [graph]...[/graph]``
|
Graphs blocks are delimited by `` [graph]...[/graph]``
|
||||||
|
|
||||||
# Properties
|
# Properties
|
||||||
|
@ -307,5 +311,5 @@ digraph UML_Class_diagram {
|
||||||
|
|
||||||
# Graphiz cache
|
# Graphiz cache
|
||||||
|
|
||||||
Rendered Graphviz graphs that have been rendered to **svg** are stored in the cache database, under table ``cached_dot``.
|
Graphviz graphs that have been rendered to **svg** are stored in the cache database, under table ``cached_dot``.
|
||||||
Unless you modify the graph or it's properties, it won't be rendered again, instead it will be sourced from the database.
|
Unless you modify the graph or it's properties, it won't be rendered again, instead it will be sourced from the database.
|
||||||
|
|
56
docs/sections.nml
Normal file
56
docs/sections.nml
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
@import template.nml
|
||||||
|
@nav.previous = Getting Started
|
||||||
|
%<make_doc({}, "Sections", "Sections")>%
|
||||||
|
|
||||||
|
#{first} Sections
|
||||||
|
|
||||||
|
To add a section to your document, put one or more ``Plain Text, #`` at the start of the line, followed a space and the name of your section.
|
||||||
|
|
||||||
|
|
||||||
|
Which will render as:
|
||||||
|
|
||||||
|
#+LAYOUT_BEGIN Split
|
||||||
|
:: Make sure they don't pollute the ToC
|
||||||
|
#+ Section name
|
||||||
|
##+ Subsection
|
||||||
|
##*+ Unnumbered section
|
||||||
|
##+ Unnumbered section
|
||||||
|
#+ This section is not in the ToC
|
||||||
|
|
||||||
|
#+LAYOUT_NEXT
|
||||||
|
|
||||||
|
Given by the following:
|
||||||
|
``
|
||||||
|
# Section name
|
||||||
|
## Subsection
|
||||||
|
#* Unnumbered section
|
||||||
|
#+ This section is not in the ToC
|
||||||
|
``
|
||||||
|
#+LAYOUT_END
|
||||||
|
|
||||||
|
# Sections references
|
||||||
|
|
||||||
|
You can create a referenceable section by using ``Plain Text, #{refname}``, where `refname` is an internal reference name for use only within this document.
|
||||||
|
You can then create a clickable reference to this section: ``§{refname}`` or ``§{refname}[caption=Click me!]``. Below is an example of this in action:
|
||||||
|
|
||||||
|
###{refname}+* Section
|
||||||
|
§{refname}[caption=Click me!] or §{first}[caption=First section]
|
||||||
|
|
||||||
|
``
|
||||||
|
###{refname}+* Section
|
||||||
|
§{refname}[caption=Click me!] or §{first}[caption=First section]
|
||||||
|
``
|
||||||
|
|
||||||
|
# Section styling
|
||||||
|
|
||||||
|
The styling for the section link is controlled by the style key ``style.section``
|
||||||
|
|
||||||
|
* ``link_pos``: `Before|After|None` Position of the section link.
|
||||||
|
* ``link``: `[Before, Link, After]` 3 strings-array
|
||||||
|
|
||||||
|
```JSON, Default Style
|
||||||
|
{
|
||||||
|
"link_pos": "Before",
|
||||||
|
"link": ["", "🔗", " "]
|
||||||
|
}
|
||||||
|
```
|
32
docs/start.nml
Normal file
32
docs/start.nml
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
@import template.nml
|
||||||
|
@nav.previous = Index
|
||||||
|
%<make_doc({}, "Getting Started", "Getting Started")>%
|
||||||
|
|
||||||
|
# Building NML
|
||||||
|
|
||||||
|
You need at least the nightly version of rustc to compile NML.
|
||||||
|
Instruction for your operating system can be found on [Rust's website](https://forge.rust-lang.org/infra/other-installation-methods.html).
|
||||||
|
You'll also need liblua 5.4 installed. You can then move the `nml` executable in `target/release/nml` into your `\$PATH`
|
||||||
|
|
||||||
|
``cargo build --bin nml`` or for release mode: ``cargo build --release --bin nml``
|
||||||
|
|
||||||
|
# Building your first document
|
||||||
|
|
||||||
|
* ``nml -i input.nml -o output.html``
|
||||||
|
|
||||||
|
# Using the cache
|
||||||
|
|
||||||
|
NML relies on sqlite to keep a cache of precompiled elements that take a long time to process (e.g $|[kind=inline] \LaTeX|$).
|
||||||
|
To enable caching, use option `-d` with a path: ``-d cache.db``. You can reuse the same cache for multiple documents and benefit from cached elements.
|
||||||
|
Note that in directory-processing mode, a cache is required so that only modified ``.nml`` files get reprocessed.
|
||||||
|
|
||||||
|
# Directory-Processing mode
|
||||||
|
|
||||||
|
To use directory-processing mode, you need to pass an input directory and an output directory. Directory-processing mode requires that you use a database, so that it knows which documents have already been compiled. If the output directory doesn't exist, it will be automatically created.
|
||||||
|
|
||||||
|
Compiling the docs:
|
||||||
|
``Plain Text,
|
||||||
|
nml -i docs -o docs_out -d cache.db
|
||||||
|
``
|
||||||
|
|
||||||
|
If you modify an ``Plain Text,@import``ed file, you will need to use the ``--force-rebuild`` option, as NML currently doesn't track which files are imported by other files.
|
|
@ -46,17 +46,17 @@ First
|
||||||
|
|
||||||
Centered layout align text to the center of the current block.
|
Centered layout align text to the center of the current block.
|
||||||
|
|
||||||
#### Style
|
####+* Style
|
||||||
The ``Centered`` layout uses the `.centered` css class to center the text.
|
The ``Centered`` layout uses the `.centered` css class to center the text.
|
||||||
|
|
||||||
#### Properties
|
####+* Properties
|
||||||
* ``style`` Added css style to the div (defaults to none)
|
* ``style`` Added css style to the div (defaults to none)
|
||||||
|
|
||||||
## Split
|
## Split
|
||||||
|
|
||||||
#### Style
|
####+* Style
|
||||||
The ``Split`` layout uses the `.split-container` and `.split` css class to create the desired layout.
|
The ``Split`` layout uses the `.split-container` and `.split` css class to create the desired layout.
|
||||||
If you wish to modify the relative width of the splits: add `style=flex: 0.5` in the properties, this makes the following split half the width of the other splits.
|
If you wish to modify the relative width of the splits: add `style=flex: 0.5` in the properties, this makes the following split half the width of the other splits.
|
||||||
|
|
||||||
#### Properties
|
####+* Properties
|
||||||
* ``style`` Added css style to the div (defaults to none)
|
* ``style`` Added css style to the div (defaults to none)
|
||||||
|
|
|
@ -1,4 +1,39 @@
|
||||||
@import ../template.nml
|
@import ../template.nml
|
||||||
%<make_doc({"Styles"}, "User-Defined", "User-Defined Styles")>%
|
%<make_doc({"Styles"}, "User-Defined", "User-Defined Styles")>%
|
||||||
|
|
||||||
# TODO
|
# Defining a custom style
|
||||||
|
```Lua
|
||||||
|
%<[main]
|
||||||
|
function undercustom_start(color)
|
||||||
|
nml.raw.push("inline", "<span style=\"border-bottom: 1px dashed " .. color .. "\">")
|
||||||
|
end
|
||||||
|
|
||||||
|
function undercustom_end()
|
||||||
|
nml.raw.push("inline", "</span>")
|
||||||
|
end
|
||||||
|
|
||||||
|
nml.custom_style.define_toggled("Undercustom Red", "~", "undercustom_start(\"red\")", "undercustom_end()")
|
||||||
|
nml.custom_style.define_paired("Undercustom Green", "[|", "|]", "undercustom_start(\"Green\")", "undercustom_end()")
|
||||||
|
>%
|
||||||
|
```
|
||||||
|
|
||||||
|
%<[main]
|
||||||
|
function undercustom_start(color)
|
||||||
|
nml.raw.push("inline", "<span style=\"border-bottom: 1px dashed " .. color .. "\">")
|
||||||
|
end
|
||||||
|
|
||||||
|
function undercustom_end()
|
||||||
|
nml.raw.push("inline", "</span>")
|
||||||
|
end
|
||||||
|
|
||||||
|
nml.custom_style.define_toggled("Undercustom Red", "~", "undercustom_start(\"red\")", "undercustom_end()")
|
||||||
|
nml.custom_style.define_paired("Undercustom Green", "[|", "|]", "undercustom_start(\"Green\")", "undercustom_end()")
|
||||||
|
>%
|
||||||
|
Results in the following:
|
||||||
|
* ``Plain Text,~Dashed underline~`` → ~Dashed underline~
|
||||||
|
* ``Plain Text,[|Dashed underline|]`` → [|Dashed underline|]
|
||||||
|
|
||||||
|
# Limitations
|
||||||
|
|
||||||
|
* Custom styles cannot be removed and will be defined through the entire document
|
||||||
|
* Custom styles defined from lua must have their `start` and `end` functions in the `main` lua kernel.
|
||||||
|
|
|
@ -92,8 +92,6 @@ impl RegexRule for CommentRule {
|
||||||
|
|
||||||
return reports;
|
return reports;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -17,7 +17,6 @@ use crate::document::customstyle::CustomStyle;
|
||||||
use crate::document::customstyle::CustomStyleToken;
|
use crate::document::customstyle::CustomStyleToken;
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::document::document::DocumentAccessors;
|
use crate::document::document::DocumentAccessors;
|
||||||
use crate::lua::kernel::function_with_context;
|
|
||||||
use crate::lua::kernel::KernelContext;
|
use crate::lua::kernel::KernelContext;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
use crate::parser::parser::Parser;
|
use crate::parser::parser::Parser;
|
||||||
|
@ -423,6 +422,18 @@ impl Rule for CustomStyleRule {
|
||||||
)| {
|
)| {
|
||||||
let mut result = Ok(());
|
let mut result = Ok(());
|
||||||
|
|
||||||
|
if token_start == token_end
|
||||||
|
{
|
||||||
|
return Err(BadArgument {
|
||||||
|
to: Some("define_paired".to_string()),
|
||||||
|
pos: 3,
|
||||||
|
name: Some("token_end".to_string()),
|
||||||
|
cause: Arc::new(mlua::Error::external(format!(
|
||||||
|
"Custom style with name `{name}` cannot be defined: The start token must differ from the end token, use `define_toggled` insteda"
|
||||||
|
))),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let style = LuaCustomStyle {
|
let style = LuaCustomStyle {
|
||||||
tokens: CustomStyleToken::Pair(token_start, token_end),
|
tokens: CustomStyleToken::Pair(token_start, token_end),
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
|
@ -434,7 +445,7 @@ impl Rule for CustomStyleRule {
|
||||||
ctx.as_ref().map(|ctx| {
|
ctx.as_ref().map(|ctx| {
|
||||||
if let Some(_) = ctx.parser.get_custom_style(name.as_str()) {
|
if let Some(_) = ctx.parser.get_custom_style(name.as_str()) {
|
||||||
result = Err(BadArgument {
|
result = Err(BadArgument {
|
||||||
to: Some("define_toggled".to_string()),
|
to: Some("define_paired".to_string()),
|
||||||
pos: 1,
|
pos: 1,
|
||||||
name: Some("name".to_string()),
|
name: Some("name".to_string()),
|
||||||
cause: Arc::new(mlua::Error::external(format!(
|
cause: Arc::new(mlua::Error::external(format!(
|
||||||
|
|
|
@ -373,7 +373,7 @@ impl Rule for ListRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse entry content
|
// Parse entry content
|
||||||
let token = Token::new(end_cursor.pos..end_cursor.pos, end_cursor.source.clone());
|
let token = Token::new(entry_start..end_cursor.pos, end_cursor.source.clone());
|
||||||
let entry_src = Rc::new(VirtualSource::new(
|
let entry_src = Rc::new(VirtualSource::new(
|
||||||
token.clone(),
|
token.clone(),
|
||||||
"List Entry".to_string(),
|
"List Entry".to_string(),
|
||||||
|
|
|
@ -409,6 +409,7 @@ mod section_style {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::document::style::StyleHolder;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
@ -472,4 +473,29 @@ nml.section.push("6", 6, "", "refname")
|
||||||
Section { depth == 6, title == "6", reference == Some("refname".to_string()) };
|
Section { depth == 6, title == "6", reference == Some("refname".to_string()) };
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn style() {
|
||||||
|
let source = Rc::new(SourceFile::with_content(
|
||||||
|
"".to_string(),
|
||||||
|
r#"
|
||||||
|
@@style.section = {
|
||||||
|
"link_pos": "None",
|
||||||
|
"link": ["a", "b", "c"]
|
||||||
|
}
|
||||||
|
"#
|
||||||
|
.to_string(),
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
let parser = LangParser::default();
|
||||||
|
let _ = parser.parse(source, None);
|
||||||
|
|
||||||
|
let style = parser
|
||||||
|
.current_style(section_style::STYLE_KEY)
|
||||||
|
.downcast_rc::<SectionStyle>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(style.link_pos, SectionLinkPos::None);
|
||||||
|
assert_eq!(style.link, ["a".to_string(), "b".to_string(), "c".to_string()]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,19 +76,3 @@ pub trait KernelHolder {
|
||||||
|
|
||||||
fn insert_kernel(&self, name: String, kernel: Kernel) -> RefMut<'_, Kernel>;
|
fn insert_kernel(&self, name: String, kernel: Kernel) -> RefMut<'_, Kernel>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs a lua function with a context
|
|
||||||
///
|
|
||||||
/// This is the only way lua functions shoule be ran, because exported
|
|
||||||
/// functions may require the context in order to operate
|
|
||||||
pub fn function_with_context<'lua, A, R>(context: KernelContext, fun: &Function<'lua>, args: A) -> Result<R, Error>
|
|
||||||
where
|
|
||||||
A: IntoLuaMulti<'lua>,
|
|
||||||
R: FromLuaMulti<'lua>,
|
|
||||||
{
|
|
||||||
CTX.set(Some(unsafe { std::mem::transmute(context) }));
|
|
||||||
let ret = fun.call::<A, R>(args);
|
|
||||||
CTX.set(None);
|
|
||||||
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::any::Any;
|
||||||
use std::cell::Ref;
|
use std::cell::Ref;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cell::RefMut;
|
use std::cell::RefMut;
|
||||||
|
@ -48,6 +49,8 @@ pub struct LangParser {
|
||||||
|
|
||||||
// Parser state
|
// Parser state
|
||||||
pub err_flag: RefCell<bool>,
|
pub err_flag: RefCell<bool>,
|
||||||
|
pub matches: RefCell<Vec<(usize, Option<Box<dyn Any>>)>>,
|
||||||
|
|
||||||
pub state: RefCell<StateHolder>,
|
pub state: RefCell<StateHolder>,
|
||||||
pub kernels: RefCell<HashMap<String, Kernel>>,
|
pub kernels: RefCell<HashMap<String, Kernel>>,
|
||||||
pub styles: RefCell<HashMap<String, Rc<dyn ElementStyle>>>,
|
pub styles: RefCell<HashMap<String, Rc<dyn ElementStyle>>>,
|
||||||
|
@ -61,6 +64,7 @@ impl LangParser {
|
||||||
rules: vec![],
|
rules: vec![],
|
||||||
colors: ReportColors::with_colors(),
|
colors: ReportColors::with_colors(),
|
||||||
err_flag: RefCell::new(false),
|
err_flag: RefCell::new(false),
|
||||||
|
matches: RefCell::new(Vec::new()),
|
||||||
state: RefCell::new(StateHolder::new()),
|
state: RefCell::new(StateHolder::new()),
|
||||||
kernels: RefCell::new(HashMap::new()),
|
kernels: RefCell::new(HashMap::new()),
|
||||||
styles: RefCell::new(HashMap::new()),
|
styles: RefCell::new(HashMap::new()),
|
||||||
|
|
|
@ -13,6 +13,7 @@ use crate::document::document::Document;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::document::layout::LayoutHolder;
|
use crate::document::layout::LayoutHolder;
|
||||||
use crate::document::style::StyleHolder;
|
use crate::document::style::StyleHolder;
|
||||||
|
use crate::elements::customstyle::CustomStyleRule;
|
||||||
use crate::lua::kernel::KernelHolder;
|
use crate::lua::kernel::KernelHolder;
|
||||||
use ariadne::Color;
|
use ariadne::Color;
|
||||||
|
|
||||||
|
@ -50,7 +51,9 @@ pub trait Parser: KernelHolder + StyleHolder + LayoutHolder + CustomStyleHolder
|
||||||
/// When colors are disabled, all colors should resolve to empty string
|
/// When colors are disabled, all colors should resolve to empty string
|
||||||
fn colors(&self) -> &ReportColors;
|
fn colors(&self) -> &ReportColors;
|
||||||
|
|
||||||
|
/// Gets a reference to all the [`Rule`]s defined for the parser
|
||||||
fn rules(&self) -> &Vec<Box<dyn Rule>>;
|
fn rules(&self) -> &Vec<Box<dyn Rule>>;
|
||||||
|
/// Gets a mutable reference to all the [`Rule`]s defined for the parser
|
||||||
fn rules_mut(&mut self) -> &mut Vec<Box<dyn Rule>>;
|
fn rules_mut(&mut self) -> &mut Vec<Box<dyn Rule>>;
|
||||||
|
|
||||||
fn state(&self) -> Ref<'_, StateHolder>;
|
fn state(&self) -> Ref<'_, StateHolder>;
|
||||||
|
@ -84,18 +87,13 @@ pub trait ParserStrategy {
|
||||||
|
|
||||||
impl<T: Parser> ParserStrategy for T {
|
impl<T: Parser> ParserStrategy for T {
|
||||||
fn add_rule(&mut self, rule: Box<dyn Rule>, after: Option<&'static str>) -> Result<(), String> {
|
fn add_rule(&mut self, rule: Box<dyn Rule>, after: Option<&'static str>) -> Result<(), String> {
|
||||||
// Error on duplicate rule
|
|
||||||
let rule_name = (*rule).name();
|
let rule_name = (*rule).name();
|
||||||
if let Err(e) = self.rules().iter().try_for_each(|rule| {
|
// Error on duplicate rule
|
||||||
if (*rule).name() != rule_name {
|
if let Some(_) = self.rules().iter().find(|rule| rule.name() == rule_name)
|
||||||
return Ok(());
|
{
|
||||||
}
|
|
||||||
|
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Attempted to introduce duplicate rule: `{rule_name}`"
|
"Attempted to introduce duplicate rule: `{rule_name}`"
|
||||||
));
|
));
|
||||||
}) {
|
|
||||||
return Err(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match after {
|
match after {
|
||||||
|
@ -134,7 +132,7 @@ impl<T: Parser> ParserStrategy for T {
|
||||||
.zip(matches.iter_mut())
|
.zip(matches.iter_mut())
|
||||||
.for_each(|(rule, (matched_at, match_data))| {
|
.for_each(|(rule, (matched_at, match_data))| {
|
||||||
// Don't upate if not stepped over yet
|
// Don't upate if not stepped over yet
|
||||||
if *matched_at > cursor.pos && rule.downcast_ref::<crate::elements::customstyle::CustomStyleRule>().is_none() {
|
if *matched_at > cursor.pos && rule.downcast_ref::<CustomStyleRule>().is_none() {
|
||||||
// TODO: maybe we should expose matches() so it becomes possible to dynamically register a new rule
|
// TODO: maybe we should expose matches() so it becomes possible to dynamically register a new rule
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue