commit
53eab4b3fd
|
@ -108,12 +108,15 @@ name = "aiken-project"
|
||||||
version = "0.0.26"
|
version = "0.0.26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aiken-lang",
|
"aiken-lang",
|
||||||
|
"askama",
|
||||||
"hex",
|
"hex",
|
||||||
"ignore",
|
"ignore",
|
||||||
|
"itertools",
|
||||||
"miette",
|
"miette",
|
||||||
"pallas",
|
"pallas",
|
||||||
"pallas-traverse",
|
"pallas-traverse",
|
||||||
"petgraph",
|
"petgraph",
|
||||||
|
"pulldown-cmark",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -135,6 +138,52 @@ version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "askama"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d298738b6e47e1034e560e5afe63aa488fea34e25ec11b855a76f0d7b8e73134"
|
||||||
|
dependencies = [
|
||||||
|
"askama_derive",
|
||||||
|
"askama_escape",
|
||||||
|
"askama_shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "askama_derive"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca2925c4c290382f9d2fa3d1c1b6a63fa1427099721ecca4749b154cc9c25522"
|
||||||
|
dependencies = [
|
||||||
|
"askama_shared",
|
||||||
|
"proc-macro2",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "askama_escape"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "askama_shared"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d6083ccb191711e9c2b80b22ee24a8381a18524444914c746d4239e21d1afaf"
|
||||||
|
dependencies = [
|
||||||
|
"askama_escape",
|
||||||
|
"humansize",
|
||||||
|
"nom",
|
||||||
|
"num-traits",
|
||||||
|
"percent-encoding",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"serde",
|
||||||
|
"syn",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
@ -200,6 +249,18 @@ version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitvec"
|
||||||
|
version = "0.19.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33"
|
||||||
|
dependencies = [
|
||||||
|
"funty",
|
||||||
|
"radium",
|
||||||
|
"tap",
|
||||||
|
"wyz",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
|
@ -389,6 +450,12 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "funty"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
|
@ -455,6 +522,12 @@ version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humansize"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -535,6 +608,19 @@ version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lexical-core"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if",
|
||||||
|
"ryu",
|
||||||
|
"static_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.133"
|
version = "0.2.133"
|
||||||
|
@ -642,6 +728,19 @@ dependencies = [
|
||||||
"adler",
|
"adler",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "6.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
|
||||||
|
dependencies = [
|
||||||
|
"bitvec",
|
||||||
|
"funty",
|
||||||
|
"lexical-core",
|
||||||
|
"memchr",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
|
@ -937,6 +1036,17 @@ dependencies = [
|
||||||
"tempfile",
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pulldown-cmark"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"memchr",
|
||||||
|
"unicase",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-error"
|
name = "quick-error"
|
||||||
version = "1.2.3"
|
version = "1.2.3"
|
||||||
|
@ -958,6 +1068,12 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "radium"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
|
@ -1120,6 +1236,12 @@ version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
|
checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
@ -1184,6 +1306,12 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tap"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.3.0"
|
version = "3.3.0"
|
||||||
|
@ -1334,6 +1462,15 @@ version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
|
checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicase"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
||||||
|
dependencies = [
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.8"
|
version = "0.3.8"
|
||||||
|
@ -1482,6 +1619,12 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wyz"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yansi"
|
name = "yansi"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
#[derive(clap::Args)]
|
||||||
|
/// Build an Aiken project
|
||||||
|
pub struct Args {
|
||||||
|
/// Path to project
|
||||||
|
#[clap(short, long)]
|
||||||
|
directory: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// Output directory for the documentation
|
||||||
|
#[clap(short = 'o', long)]
|
||||||
|
destination: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exec(
|
||||||
|
Args {
|
||||||
|
directory,
|
||||||
|
destination,
|
||||||
|
}: Args,
|
||||||
|
) -> miette::Result<()> {
|
||||||
|
crate::with_project(directory, |p| p.docs(destination.clone()))
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod build;
|
pub mod build;
|
||||||
pub mod check;
|
pub mod check;
|
||||||
|
pub mod docs;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod fmt;
|
pub mod fmt;
|
||||||
pub mod lsp;
|
pub mod lsp;
|
||||||
|
|
|
@ -68,6 +68,19 @@ impl telemetry::EventListener for Terminal {
|
||||||
root.to_str().unwrap_or("").bright_blue()
|
root.to_str().unwrap_or("").bright_blue()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
telemetry::Event::BuildingDocumentation {
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
root,
|
||||||
|
} => {
|
||||||
|
println!(
|
||||||
|
"{} {} {} ({})",
|
||||||
|
"Generating documentation".bold().purple(),
|
||||||
|
name.bold(),
|
||||||
|
version,
|
||||||
|
root.to_str().unwrap_or("").bright_blue()
|
||||||
|
);
|
||||||
|
}
|
||||||
telemetry::Event::ParsingProjectFiles => {
|
telemetry::Event::ParsingProjectFiles => {
|
||||||
println!("{}", "...Parsing project files".bold().purple());
|
println!("{}", "...Parsing project files".bold().purple());
|
||||||
}
|
}
|
||||||
|
@ -81,6 +94,13 @@ impl telemetry::EventListener for Terminal {
|
||||||
output_path.to_str().unwrap_or("").bright_blue()
|
output_path.to_str().unwrap_or("").bright_blue()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
telemetry::Event::GeneratingDocFiles { output_path } => {
|
||||||
|
println!(
|
||||||
|
"{} in {}",
|
||||||
|
"...Generating documentation files".bold().purple(),
|
||||||
|
output_path.to_str().unwrap_or("").bright_blue()
|
||||||
|
);
|
||||||
|
}
|
||||||
telemetry::Event::EvaluatingFunction { results } => {
|
telemetry::Event::EvaluatingFunction { results } => {
|
||||||
println!("{}\n", "...Evaluating function".bold().purple());
|
println!("{}\n", "...Evaluating function".bold().purple());
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use aiken::cmd::{build, check, fmt, lsp, new, tx, uplc};
|
use aiken::cmd::{build, check, docs, fmt, lsp, new, tx, uplc};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
/// Aiken: a smart-contract language and toolchain for Cardano
|
/// Aiken: a smart-contract language and toolchain for Cardano
|
||||||
|
@ -11,6 +11,7 @@ pub enum Cmd {
|
||||||
Fmt(fmt::Args),
|
Fmt(fmt::Args),
|
||||||
Build(build::Args),
|
Build(build::Args),
|
||||||
Check(check::Args),
|
Check(check::Args),
|
||||||
|
Docs(docs::Args),
|
||||||
|
|
||||||
#[clap(hide = true)]
|
#[clap(hide = true)]
|
||||||
Lsp(lsp::Args),
|
Lsp(lsp::Args),
|
||||||
|
@ -34,6 +35,7 @@ fn main() -> miette::Result<()> {
|
||||||
Cmd::New(args) => new::exec(args),
|
Cmd::New(args) => new::exec(args),
|
||||||
Cmd::Fmt(args) => fmt::exec(args),
|
Cmd::Fmt(args) => fmt::exec(args),
|
||||||
Cmd::Build(args) => build::exec(args),
|
Cmd::Build(args) => build::exec(args),
|
||||||
|
Cmd::Docs(args) => docs::exec(args),
|
||||||
Cmd::Check(args) => check::exec(args),
|
Cmd::Check(args) => check::exec(args),
|
||||||
Cmd::Lsp(args) => lsp::exec(args),
|
Cmd::Lsp(args) => lsp::exec(args),
|
||||||
Cmd::Tx(sub_cmd) => tx::exec(sub_cmd),
|
Cmd::Tx(sub_cmd) => tx::exec(sub_cmd),
|
||||||
|
|
|
@ -130,14 +130,14 @@ impl TypedDataType {
|
||||||
tipo: tipo.clone(),
|
tipo: tipo.clone(),
|
||||||
doc: None,
|
doc: None,
|
||||||
}],
|
}],
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: false,
|
sugar: false,
|
||||||
},
|
},
|
||||||
RecordConstructor {
|
RecordConstructor {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
name: "None".to_string(),
|
name: "None".to_string(),
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: false,
|
sugar: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -352,10 +352,16 @@ pub struct RecordConstructor<T> {
|
||||||
pub location: Span,
|
pub location: Span,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub arguments: Vec<RecordConstructorArg<T>>,
|
pub arguments: Vec<RecordConstructorArg<T>>,
|
||||||
pub documentation: Option<String>,
|
pub doc: Option<String>,
|
||||||
pub sugar: bool,
|
pub sugar: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A> RecordConstructor<A> {
|
||||||
|
pub fn put_doc(&mut self, new_doc: String) {
|
||||||
|
self.doc = Some(new_doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct RecordConstructorArg<T> {
|
pub struct RecordConstructorArg<T> {
|
||||||
pub label: Option<String>,
|
pub label: Option<String>,
|
||||||
|
@ -366,6 +372,12 @@ pub struct RecordConstructorArg<T> {
|
||||||
pub doc: Option<String>,
|
pub doc: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: PartialEq> RecordConstructorArg<T> {
|
||||||
|
pub fn put_doc(&mut self, new_doc: String) {
|
||||||
|
self.doc = Some(new_doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type TypedArg = Arg<Arc<Type>>;
|
pub type TypedArg = Arg<Arc<Type>>;
|
||||||
pub type UntypedArg = Arg<()>;
|
pub type UntypedArg = Arg<()>;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
const INDENT: isize = 2;
|
const INDENT: isize = 2;
|
||||||
|
const DOCS_MAX_COLUMNS: isize = 80;
|
||||||
|
|
||||||
pub fn pretty(writer: &mut String, module: UntypedModule, extra: ModuleExtra, src: &str) {
|
pub fn pretty(writer: &mut String, module: UntypedModule, extra: ModuleExtra, src: &str) {
|
||||||
let intermediate = Intermediate {
|
let intermediate = Intermediate {
|
||||||
|
@ -347,6 +348,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
} => name
|
} => name
|
||||||
.to_doc()
|
.to_doc()
|
||||||
.append(wrap_args(
|
.append(wrap_args(
|
||||||
|
false,
|
||||||
args.iter()
|
args.iter()
|
||||||
.map(|a| (self.constant_call_arg(a), a.label.is_some())),
|
.map(|a| (self.constant_call_arg(a), a.label.is_some())),
|
||||||
))
|
))
|
||||||
|
@ -362,6 +364,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
.append(".")
|
.append(".")
|
||||||
.append(name.as_str())
|
.append(name.as_str())
|
||||||
.append(wrap_args(
|
.append(wrap_args(
|
||||||
|
false,
|
||||||
args.iter()
|
args.iter()
|
||||||
.map(|a| (self.constant_call_arg(a), a.label.is_some())),
|
.map(|a| (self.constant_call_arg(a), a.label.is_some())),
|
||||||
))
|
))
|
||||||
|
@ -380,23 +383,16 @@ impl<'comments> Formatter<'comments> {
|
||||||
Constant::Tuple { elements, .. } => "#"
|
Constant::Tuple { elements, .. } => "#"
|
||||||
.to_doc()
|
.to_doc()
|
||||||
.append(wrap_args(
|
.append(wrap_args(
|
||||||
|
false,
|
||||||
elements.iter().map(|e| (self.const_expr(e), false)),
|
elements.iter().map(|e| (self.const_expr(e), false)),
|
||||||
))
|
))
|
||||||
.group(),
|
.group(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn docs_const_expr<'a>(
|
pub fn docs_const_expr<'a>(&mut self, name: &'a str, value: &'a TypedConstant) -> Document<'a> {
|
||||||
&mut self,
|
|
||||||
public: bool,
|
|
||||||
name: &'a str,
|
|
||||||
value: &'a TypedConstant,
|
|
||||||
) -> Document<'a> {
|
|
||||||
let mut printer = tipo::pretty::Printer::new();
|
let mut printer = tipo::pretty::Printer::new();
|
||||||
|
name.to_doc()
|
||||||
pub_(public)
|
|
||||||
.append("const ")
|
|
||||||
.append(name)
|
|
||||||
.append(": ")
|
.append(": ")
|
||||||
.append(printer.print(&value.tipo()))
|
.append(printer.print(&value.tipo()))
|
||||||
.append(" = ")
|
.append(" = ")
|
||||||
|
@ -459,15 +455,19 @@ impl<'comments> Formatter<'comments> {
|
||||||
..
|
..
|
||||||
} => "fn"
|
} => "fn"
|
||||||
.to_doc()
|
.to_doc()
|
||||||
.append(wrap_args(args.iter().map(|t| (self.annotation(t), false))))
|
.append(wrap_args(
|
||||||
|
false,
|
||||||
|
args.iter().map(|t| (self.annotation(t), false)),
|
||||||
|
))
|
||||||
.group()
|
.group()
|
||||||
.append(" ->")
|
.append(" ->")
|
||||||
.append(break_("", " ").append(self.annotation(retrn)).nest(INDENT)),
|
.append(break_("", " ").append(self.annotation(retrn)).nest(INDENT)),
|
||||||
|
|
||||||
Annotation::Var { name, .. } => name.to_doc(),
|
Annotation::Var { name, .. } => name.to_doc(),
|
||||||
Annotation::Tuple { elems, .. } => "#"
|
Annotation::Tuple { elems, .. } => "#".to_doc().append(wrap_args(
|
||||||
.to_doc()
|
false,
|
||||||
.append(wrap_args(elems.iter().map(|t| (self.annotation(t), false)))),
|
elems.iter().map(|t| (self.annotation(t), false)),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
.group()
|
.group()
|
||||||
}
|
}
|
||||||
|
@ -527,7 +527,10 @@ impl<'comments> Formatter<'comments> {
|
||||||
.append(keyword)
|
.append(keyword)
|
||||||
.append(" ")
|
.append(" ")
|
||||||
.append(name)
|
.append(name)
|
||||||
.append(wrap_args(args.iter().map(|e| (self.fn_arg(e), false))));
|
.append(wrap_args(
|
||||||
|
false,
|
||||||
|
args.iter().map(|e| (self.fn_arg(e), false)),
|
||||||
|
));
|
||||||
|
|
||||||
// Add return annotation
|
// Add return annotation
|
||||||
let head = match return_annotation {
|
let head = match return_annotation {
|
||||||
|
@ -558,7 +561,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
return_annotation: Option<&'a Annotation>,
|
return_annotation: Option<&'a Annotation>,
|
||||||
body: &'a UntypedExpr,
|
body: &'a UntypedExpr,
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
let args = wrap_args(args.iter().map(|e| (self.fn_arg(e), false))).group();
|
let args = wrap_args(false, args.iter().map(|e| (self.fn_arg(e), false))).group();
|
||||||
let body = match body {
|
let body = match body {
|
||||||
UntypedExpr::When { .. } => self.expr(body).force_break(),
|
UntypedExpr::When { .. } => self.expr(body).force_break(),
|
||||||
_ => self.expr(body),
|
_ => self.expr(body),
|
||||||
|
@ -788,7 +791,10 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
UntypedExpr::Tuple { elems, .. } => "#"
|
UntypedExpr::Tuple { elems, .. } => "#"
|
||||||
.to_doc()
|
.to_doc()
|
||||||
.append(wrap_args(elems.iter().map(|e| (self.wrap_expr(e), false))))
|
.append(wrap_args(
|
||||||
|
false,
|
||||||
|
elems.iter().map(|e| (self.wrap_expr(e), false)),
|
||||||
|
))
|
||||||
.group(),
|
.group(),
|
||||||
};
|
};
|
||||||
commented(document, comments)
|
commented(document, comments)
|
||||||
|
@ -852,6 +858,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
_ => name
|
_ => name
|
||||||
.append(wrap_args(
|
.append(wrap_args(
|
||||||
|
false,
|
||||||
args.iter().map(|a| (self.pattern_call_arg(a), is_record)),
|
args.iter().map(|a| (self.pattern_call_arg(a), is_record)),
|
||||||
))
|
))
|
||||||
.group(),
|
.group(),
|
||||||
|
@ -893,6 +900,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
_ => self
|
_ => self
|
||||||
.expr(fun)
|
.expr(fun)
|
||||||
.append(wrap_args(
|
.append(wrap_args(
|
||||||
|
false,
|
||||||
args.iter()
|
args.iter()
|
||||||
.map(|a| (self.call_arg(a, needs_curly), needs_curly)),
|
.map(|a| (self.call_arg(a, needs_curly), needs_curly)),
|
||||||
))
|
))
|
||||||
|
@ -940,7 +948,9 @@ impl<'comments> Formatter<'comments> {
|
||||||
let spread_doc = "..".to_doc().append(self.expr(&spread.base));
|
let spread_doc = "..".to_doc().append(self.expr(&spread.base));
|
||||||
let arg_docs = args.iter().map(|a| (self.record_update_arg(a), true));
|
let arg_docs = args.iter().map(|a| (self.record_update_arg(a), true));
|
||||||
let all_arg_docs = once((spread_doc, true)).chain(arg_docs);
|
let all_arg_docs = once((spread_doc, true)).chain(arg_docs);
|
||||||
constructor_doc.append(wrap_args(all_arg_docs)).group()
|
constructor_doc
|
||||||
|
.append(wrap_args(false, all_arg_docs))
|
||||||
|
.group()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bin_op<'a>(
|
pub fn bin_op<'a>(
|
||||||
|
@ -1026,6 +1036,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
// x |> fun(_, 2, 3)
|
// x |> fun(_, 2, 3)
|
||||||
self.expr(fun).append(
|
self.expr(fun).append(
|
||||||
wrap_args(
|
wrap_args(
|
||||||
|
false,
|
||||||
args.iter()
|
args.iter()
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.map(|a| (self.call_arg(a, false), false)),
|
.map(|a| (self.call_arg(a, false), false)),
|
||||||
|
@ -1034,8 +1045,9 @@ impl<'comments> Formatter<'comments> {
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// x |> fun(1, _, 3)
|
// x |> fun(1, _, 3)
|
||||||
self.expr(fun)
|
self.expr(fun).append(
|
||||||
.append(wrap_args(args.iter().map(|a| (self.call_arg(a, false), false))).group())
|
wrap_args(false, args.iter().map(|a| (self.call_arg(a, false), false))).group(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1055,7 +1067,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => self.expr(fun).append(
|
_ => self.expr(fun).append(
|
||||||
wrap_args(args.iter().map(|a| (self.call_arg(a, false), false))).group(),
|
wrap_args(false, args.iter().map(|a| (self.call_arg(a, false), false))).group(),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1099,29 +1111,34 @@ impl<'comments> Formatter<'comments> {
|
||||||
constructor
|
constructor
|
||||||
.name
|
.name
|
||||||
.to_doc()
|
.to_doc()
|
||||||
.append(wrap_args(constructor.arguments.iter().map(
|
.append(wrap_args(
|
||||||
|RecordConstructorArg {
|
false,
|
||||||
label,
|
constructor.arguments.iter().map(
|
||||||
annotation,
|
|RecordConstructorArg {
|
||||||
location,
|
label,
|
||||||
..
|
annotation,
|
||||||
}| {
|
location,
|
||||||
let arg_comments = self.pop_comments(location.start);
|
..
|
||||||
|
}| {
|
||||||
|
let arg_comments = self.pop_comments(location.start);
|
||||||
|
|
||||||
let arg = match label {
|
let arg = match label {
|
||||||
Some(l) => l.to_doc().append(": ").append(self.annotation(annotation)),
|
Some(l) => {
|
||||||
None => self.annotation(annotation),
|
l.to_doc().append(": ").append(self.annotation(annotation))
|
||||||
};
|
}
|
||||||
|
None => self.annotation(annotation),
|
||||||
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
commented(
|
commented(
|
||||||
self.doc_comments(location.start).append(arg).group(),
|
self.doc_comments(location.start).append(arg).group(),
|
||||||
arg_comments,
|
arg_comments,
|
||||||
),
|
),
|
||||||
label.is_some(),
|
label.is_some(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)))
|
),
|
||||||
|
))
|
||||||
.group()
|
.group()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1172,57 +1189,155 @@ impl<'comments> Formatter<'comments> {
|
||||||
.append("}")
|
.append("}")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn docs_opaque_custom_type<'a>(
|
pub fn docs_data_type<'a, A>(
|
||||||
|
&mut self,
|
||||||
|
name: &'a str,
|
||||||
|
args: &'a [String],
|
||||||
|
constructors: &'a [RecordConstructor<A>],
|
||||||
|
location: &'a Span,
|
||||||
|
) -> Document<'a> {
|
||||||
|
self.pop_empty_lines(location.start);
|
||||||
|
|
||||||
|
let mut is_sugar = false;
|
||||||
|
|
||||||
|
(if args.is_empty() {
|
||||||
|
name.to_doc()
|
||||||
|
} else {
|
||||||
|
name.to_doc()
|
||||||
|
.append(wrap_generics(args.iter().map(|e| e.to_doc())))
|
||||||
|
.group()
|
||||||
|
})
|
||||||
|
.append(" {")
|
||||||
|
.append(if constructors.len() == 1 && constructors[0].sugar {
|
||||||
|
is_sugar = true;
|
||||||
|
|
||||||
|
self.record_constructor(&constructors[0])
|
||||||
|
} else {
|
||||||
|
concat(constructors.iter().map(|c| {
|
||||||
|
if self.pop_empty_lines(c.location.start) {
|
||||||
|
lines(2)
|
||||||
|
} else {
|
||||||
|
line()
|
||||||
|
}
|
||||||
|
.append(self.record_constructor(c))
|
||||||
|
.nest(INDENT)
|
||||||
|
.group()
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
.append(if is_sugar { nil() } else { line() })
|
||||||
|
.append("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn docs_opaque_data_type<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
public: bool,
|
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
args: &'a [String],
|
args: &'a [String],
|
||||||
location: &'a Span,
|
location: &'a Span,
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
self.pop_empty_lines(location.start);
|
self.pop_empty_lines(location.start);
|
||||||
pub_(public)
|
if args.is_empty() {
|
||||||
.to_doc()
|
name.to_doc()
|
||||||
.append("opaque type ")
|
} else {
|
||||||
.append(if args.is_empty() {
|
name.to_doc()
|
||||||
name.to_doc()
|
.append(wrap_generics(args.iter().map(|e| e.to_doc())).group())
|
||||||
} else {
|
}
|
||||||
name.to_doc()
|
}
|
||||||
.append(wrap_args(args.iter().map(|e| (e.to_doc(), false))))
|
|
||||||
})
|
pub fn docs_type_alias<'a>(
|
||||||
|
&mut self,
|
||||||
|
name: &'a str,
|
||||||
|
args: &'a [String],
|
||||||
|
typ: &'a Annotation,
|
||||||
|
) -> Document<'a> {
|
||||||
|
let head = name.to_doc();
|
||||||
|
|
||||||
|
let head = if args.is_empty() {
|
||||||
|
head
|
||||||
|
} else {
|
||||||
|
head.append(wrap_generics(args.iter().map(|e| e.to_doc())).group())
|
||||||
|
};
|
||||||
|
|
||||||
|
head.append(" = ")
|
||||||
|
.append(self.annotation(typ).group().nest(INDENT))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn docs_record_constructor<'a, A>(
|
||||||
|
&mut self,
|
||||||
|
constructor: &'a RecordConstructor<A>,
|
||||||
|
) -> Document<'a> {
|
||||||
|
constructor.name.to_doc()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn docs_fn_signature<'a>(
|
pub fn docs_fn_signature<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
public: bool,
|
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
args: &'a [TypedArg],
|
args: &'a [TypedArg],
|
||||||
|
return_annotation: &'a Option<Annotation>,
|
||||||
return_type: Arc<Type>,
|
return_type: Arc<Type>,
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
let mut printer = tipo::pretty::Printer::new();
|
let head = name
|
||||||
|
.to_doc()
|
||||||
|
.append(self.docs_fn_args(false, args))
|
||||||
|
.append(" -> ");
|
||||||
|
|
||||||
pub_(public)
|
let tail = self.type_or_annotation(return_annotation, &return_type);
|
||||||
.append("fn ")
|
|
||||||
.append(name)
|
let doc = head.append(tail.clone()).group();
|
||||||
.append(self.docs_fn_args(args, &mut printer))
|
|
||||||
.append(" -> ".to_doc())
|
// Wrap arguments on multi-lines if they are lengthy.
|
||||||
.append(printer.print(&return_type))
|
if doc
|
||||||
|
.clone()
|
||||||
|
.to_pretty_string(DOCS_MAX_COLUMNS)
|
||||||
|
.contains('\n')
|
||||||
|
{
|
||||||
|
let head = name
|
||||||
|
.to_doc()
|
||||||
|
.append(self.docs_fn_args(true, args))
|
||||||
|
.append(" -> ");
|
||||||
|
head.append(tail).group()
|
||||||
|
} else {
|
||||||
|
doc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Will always print the types, even if they were implicit in the original source
|
// Will always print the types, even if they were implicit in the original source
|
||||||
pub fn docs_fn_args<'a>(
|
pub fn docs_fn_args<'a>(&mut self, multiline: bool, args: &'a [TypedArg]) -> Document<'a> {
|
||||||
|
if multiline {
|
||||||
|
line().nest(INDENT).append(wrap_args(
|
||||||
|
true,
|
||||||
|
args.iter()
|
||||||
|
.map(|e| (self.docs_fn_arg(e).append(line()), false)),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
wrap_args(false, args.iter().map(|e| (self.docs_fn_arg(e), false)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn docs_fn_arg<'a>(&mut self, arg: &'a Arg<Arc<Type>>) -> Document<'a> {
|
||||||
|
self.docs_fn_arg_name(&arg.arg_name)
|
||||||
|
.append(self.type_or_annotation(&arg.annotation, &arg.tipo))
|
||||||
|
.group()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn docs_fn_arg_name<'a>(&mut self, arg_name: &'a ArgName) -> Document<'a> {
|
||||||
|
match arg_name {
|
||||||
|
ArgName::Named { .. } | ArgName::Discard { .. } => "".to_doc(),
|
||||||
|
ArgName::LabeledDiscard { label, .. } | ArgName::NamedLabeled { label, .. } => {
|
||||||
|
label.to_doc().append(": ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display type-annotation when available, or fallback to inferred type.
|
||||||
|
fn type_or_annotation<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
args: &'a [TypedArg],
|
annotation: &'a Option<Annotation>,
|
||||||
printer: &mut tipo::pretty::Printer,
|
type_info: &Arc<Type>,
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
wrap_args(args.iter().map(|arg| {
|
match annotation {
|
||||||
(
|
Some(a) => self.annotation(a),
|
||||||
arg.arg_name
|
None => tipo::pretty::Printer::new().print(type_info),
|
||||||
.to_doc()
|
}
|
||||||
.append(": ".to_doc().append(printer.print(&arg.tipo)))
|
|
||||||
.group(),
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrap_expr<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
|
fn wrap_expr<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
|
||||||
|
@ -1355,7 +1470,10 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
Pattern::Tuple { elems, .. } => "#"
|
Pattern::Tuple { elems, .. } => "#"
|
||||||
.to_doc()
|
.to_doc()
|
||||||
.append(wrap_args(elems.iter().map(|e| (self.pattern(e), false))))
|
.append(wrap_args(
|
||||||
|
false,
|
||||||
|
elems.iter().map(|e| (self.pattern(e), false)),
|
||||||
|
))
|
||||||
.group(),
|
.group(),
|
||||||
|
|
||||||
Pattern::List { elements, tail, .. } => {
|
Pattern::List { elements, tail, .. } => {
|
||||||
|
@ -1511,7 +1629,7 @@ impl<'a> Documentable<'a> for &'a BinOp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wrap_args<'a, I>(args: I) -> Document<'a>
|
pub fn wrap_args<'a, I>(multiline: bool, args: I) -> Document<'a>
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = (Document<'a>, bool)>,
|
I: IntoIterator<Item = (Document<'a>, bool)>,
|
||||||
{
|
{
|
||||||
|
@ -1527,6 +1645,8 @@ where
|
||||||
|
|
||||||
let (open_broken, open_unbroken, close) = if curly {
|
let (open_broken, open_unbroken, close) = if curly {
|
||||||
(" {", " { ", "}")
|
(" {", " { ", "}")
|
||||||
|
} else if multiline {
|
||||||
|
("( ", "( ", ")")
|
||||||
} else {
|
} else {
|
||||||
("(", "(", ")")
|
("(", "(", ")")
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,22 +33,18 @@ pub fn module(
|
||||||
let tokens = tokens.into_iter().filter(|(token, span)| match token {
|
let tokens = tokens.into_iter().filter(|(token, span)| match token {
|
||||||
Token::ModuleComment => {
|
Token::ModuleComment => {
|
||||||
extra.module_comments.push(*span);
|
extra.module_comments.push(*span);
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
Token::DocComment => {
|
Token::DocComment => {
|
||||||
extra.doc_comments.push(*span);
|
extra.doc_comments.push(*span);
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
Token::Comment => {
|
Token::Comment => {
|
||||||
extra.comments.push(*span);
|
extra.comments.push(*span);
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
Token::EmptyLine => {
|
Token::EmptyLine => {
|
||||||
extra.empty_lines.push(span.start);
|
extra.empty_lines.push(span.start);
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
Token::NewLine => false,
|
Token::NewLine => false,
|
||||||
|
@ -157,7 +153,7 @@ pub fn data_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = Parse
|
||||||
location: span,
|
location: span,
|
||||||
arguments: arguments.unwrap_or_default(),
|
arguments: arguments.unwrap_or_default(),
|
||||||
name,
|
name,
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: false,
|
sugar: false,
|
||||||
})
|
})
|
||||||
.repeated()
|
.repeated()
|
||||||
|
@ -167,7 +163,7 @@ pub fn data_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = Parse
|
||||||
vec![ast::RecordConstructor {
|
vec![ast::RecordConstructor {
|
||||||
location: span,
|
location: span,
|
||||||
arguments,
|
arguments,
|
||||||
documentation: None,
|
doc: None,
|
||||||
name: String::from("_replace"),
|
name: String::from("_replace"),
|
||||||
sugar: true,
|
sugar: true,
|
||||||
}]
|
}]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::ast::Span;
|
use crate::ast::Span;
|
||||||
|
use std::iter::Peekable;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Default, Clone)]
|
#[derive(Debug, PartialEq, Eq, Default, Clone)]
|
||||||
pub struct ModuleExtra {
|
pub struct ModuleExtra {
|
||||||
|
@ -33,3 +34,22 @@ impl<'a> From<(&Span, &'a str)> for Comment<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn comments_before<'a>(
|
||||||
|
comment_spans: &mut Peekable<impl Iterator<Item = &'a Span>>,
|
||||||
|
byte: usize,
|
||||||
|
src: &'a str,
|
||||||
|
) -> Vec<&'a str> {
|
||||||
|
let mut comments = vec![];
|
||||||
|
while let Some(Span { start, .. }) = comment_spans.peek() {
|
||||||
|
if start <= &byte {
|
||||||
|
let comment = comment_spans
|
||||||
|
.next()
|
||||||
|
.expect("Comment before accessing next span");
|
||||||
|
comments.push(Comment::from((comment, src)).content)
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
comments
|
||||||
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ fn unqualified_imports() {
|
||||||
#[test]
|
#[test]
|
||||||
fn import_alias() {
|
fn import_alias() {
|
||||||
let code = indoc! {r#"
|
let code = indoc! {r#"
|
||||||
use std/tx as t
|
use std/tx as t
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definition(
|
||||||
|
@ -130,14 +130,14 @@ fn custom_type() {
|
||||||
doc: None,
|
doc: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: false,
|
sugar: false,
|
||||||
},
|
},
|
||||||
ast::RecordConstructor {
|
ast::RecordConstructor {
|
||||||
location: Span::new((), 34..38),
|
location: Span::new((), 34..38),
|
||||||
name: "None".to_string(),
|
name: "None".to_string(),
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: false,
|
sugar: false,
|
||||||
},
|
},
|
||||||
ast::RecordConstructor {
|
ast::RecordConstructor {
|
||||||
|
@ -169,7 +169,7 @@ fn custom_type() {
|
||||||
doc: None,
|
doc: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: false,
|
sugar: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -208,7 +208,7 @@ fn opaque_type() {
|
||||||
tipo: (),
|
tipo: (),
|
||||||
doc: None,
|
doc: None,
|
||||||
}],
|
}],
|
||||||
documentation: None,
|
doc: None,
|
||||||
sugar: true,
|
sugar: true,
|
||||||
}],
|
}],
|
||||||
doc: None,
|
doc: None,
|
||||||
|
@ -285,7 +285,7 @@ fn pub_type_alias() {
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_function() {
|
fn empty_function() {
|
||||||
let code = indoc! {r#"
|
let code = indoc! {r#"
|
||||||
pub fn run() {}
|
pub fn run() {}
|
||||||
"#};
|
"#};
|
||||||
|
|
||||||
assert_definition(
|
assert_definition(
|
||||||
|
|
|
@ -288,7 +288,7 @@ fn infer_definition(
|
||||||
location,
|
location,
|
||||||
name,
|
name,
|
||||||
arguments: args,
|
arguments: args,
|
||||||
documentation,
|
doc,
|
||||||
sugar,
|
sugar,
|
||||||
}| {
|
}| {
|
||||||
let preregistered_fn = environment
|
let preregistered_fn = environment
|
||||||
|
@ -330,7 +330,7 @@ fn infer_definition(
|
||||||
location,
|
location,
|
||||||
name,
|
name,
|
||||||
arguments: args,
|
arguments: args,
|
||||||
documentation,
|
doc,
|
||||||
sugar,
|
sugar,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -61,9 +61,9 @@ impl Printer {
|
||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
doc
|
doc
|
||||||
} else {
|
} else {
|
||||||
doc.append("(")
|
doc.append("<")
|
||||||
.append(self.args_to_aiken_doc(args))
|
.append(self.args_to_aiken_doc(args))
|
||||||
.append(")")
|
.append(">")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +298,7 @@ mod test {
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"Pair(Int, Bool)",
|
"Pair<Int, Bool>",
|
||||||
);
|
);
|
||||||
assert_string!(
|
assert_string!(
|
||||||
Type::Fn {
|
Type::Fn {
|
||||||
|
|
|
@ -10,16 +10,19 @@ authors = ["Lucas Rosa <x@rvcas.dev>", "Kasey White <kwhitemsg@gmail.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aiken-lang = { path = "../lang", version = "0.0.26" }
|
aiken-lang = { path = "../lang", version = "0.0.26" }
|
||||||
|
askama = "0.10.5"
|
||||||
|
hex = "0.4.3"
|
||||||
ignore = "0.4.18"
|
ignore = "0.4.18"
|
||||||
uplc = { path = '../uplc', version = "0.0.25" }
|
itertools = "0.10.1"
|
||||||
miette = { version = "5.3.0", features = ["fancy"] }
|
miette = { version = "5.3.0", features = ["fancy"] }
|
||||||
|
pallas = "0.14.0"
|
||||||
|
pallas-traverse = "0.14.0"
|
||||||
petgraph = "0.6.2"
|
petgraph = "0.6.2"
|
||||||
|
pulldown-cmark = { version = "0.8.0", default-features = false }
|
||||||
regex = "1.6.0"
|
regex = "1.6.0"
|
||||||
serde = { version = "1.0.144", features = ["derive"] }
|
serde = { version = "1.0.144", features = ["derive"] }
|
||||||
serde_json = { version = "1.0.85", features = ["preserve_order"] }
|
serde_json = { version = "1.0.85", features = ["preserve_order"] }
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
toml = "0.5.9"
|
toml = "0.5.9"
|
||||||
|
uplc = { path = '../uplc', version = "0.0.25" }
|
||||||
walkdir = "2.3.2"
|
walkdir = "2.3.2"
|
||||||
hex = "0.4.3"
|
|
||||||
pallas = "0.14.0"
|
|
||||||
pallas-traverse = "0.14.0"
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{fs, io, path::PathBuf};
|
use std::{fmt::Display, fs, io, path::PathBuf};
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
@ -8,6 +8,31 @@ pub struct Config {
|
||||||
pub version: String,
|
pub version: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub description: String,
|
pub description: String,
|
||||||
|
pub repository: Option<Repository>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct Repository {
|
||||||
|
pub user: String,
|
||||||
|
pub project: String,
|
||||||
|
pub platform: Platform,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub enum Platform {
|
||||||
|
Github,
|
||||||
|
Gitlab,
|
||||||
|
Bitbucket,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Platform {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
|
||||||
|
match *self {
|
||||||
|
Platform::Github => f.write_str("github"),
|
||||||
|
Platform::Gitlab => f.write_str("gitlab"),
|
||||||
|
Platform::Bitbucket => f.write_str("bitbucket"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
|
|
@ -0,0 +1,680 @@
|
||||||
|
use crate::{
|
||||||
|
config::{Config, Repository},
|
||||||
|
module::CheckedModule,
|
||||||
|
};
|
||||||
|
use aiken_lang::{
|
||||||
|
ast::{Definition, RecordConstructor, RecordConstructorArg, TypedDefinition},
|
||||||
|
format,
|
||||||
|
tipo::Type,
|
||||||
|
};
|
||||||
|
use askama::Template;
|
||||||
|
use itertools::Itertools;
|
||||||
|
use pulldown_cmark as markdown;
|
||||||
|
use serde::Serialize;
|
||||||
|
use serde_json as json;
|
||||||
|
use std::{
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
sync::Arc,
|
||||||
|
time::{Duration, SystemTime},
|
||||||
|
};
|
||||||
|
|
||||||
|
const MAX_COLUMNS: isize = 999;
|
||||||
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
|
pub struct DocFile {
|
||||||
|
pub path: PathBuf,
|
||||||
|
pub content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "module.html")]
|
||||||
|
struct ModuleTemplate<'a> {
|
||||||
|
aiken_version: &'a str,
|
||||||
|
breadcrumbs: String,
|
||||||
|
page_title: &'a str,
|
||||||
|
module_name: String,
|
||||||
|
project_name: &'a str,
|
||||||
|
project_version: &'a str,
|
||||||
|
modules_prefix: String,
|
||||||
|
modules: &'a Vec<DocLink>,
|
||||||
|
functions: Vec<DocFunction>,
|
||||||
|
types: Vec<DocType>,
|
||||||
|
constants: Vec<DocConstant>,
|
||||||
|
documentation: String,
|
||||||
|
source: &'a DocLink,
|
||||||
|
timestamp: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ModuleTemplate<'a> {
|
||||||
|
pub fn is_current_module(&self, module: &DocLink) -> bool {
|
||||||
|
match module.path.split(".html").next() {
|
||||||
|
None => false,
|
||||||
|
Some(name) => self.module_name == name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "page.html")]
|
||||||
|
struct PageTemplate<'a> {
|
||||||
|
aiken_version: &'a str,
|
||||||
|
breadcrumbs: &'a str,
|
||||||
|
page_title: &'a str,
|
||||||
|
project_name: &'a str,
|
||||||
|
project_version: &'a str,
|
||||||
|
modules_prefix: String,
|
||||||
|
modules: &'a Vec<DocLink>,
|
||||||
|
content: String,
|
||||||
|
source: &'a DocLink,
|
||||||
|
timestamp: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PageTemplate<'a> {
|
||||||
|
pub fn is_current_module(&self, _module: &DocLink) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
|
struct DocLink {
|
||||||
|
name: String,
|
||||||
|
path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DocLink {
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.name.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate documentation files for a given project.
|
||||||
|
///
|
||||||
|
/// The documentation is built using template files located at the root of this crate.
|
||||||
|
/// With the documentation, we also build a client-side search index to ease navigation
|
||||||
|
/// across multiple modules.
|
||||||
|
pub fn generate_all(root: &Path, config: &Config, modules: Vec<&CheckedModule>) -> Vec<DocFile> {
|
||||||
|
let timestamp = new_timestamp();
|
||||||
|
let (modules_prefix, modules_links) = generate_modules_links(&modules);
|
||||||
|
|
||||||
|
let source = match &config.repository {
|
||||||
|
None => DocLink {
|
||||||
|
name: String::new(),
|
||||||
|
path: String::new(),
|
||||||
|
},
|
||||||
|
Some(Repository {
|
||||||
|
user,
|
||||||
|
project,
|
||||||
|
platform,
|
||||||
|
}) => DocLink {
|
||||||
|
name: format!("{user}/{project}"),
|
||||||
|
path: format!("https://{platform}.com/{user}/{project}"),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut output_files: Vec<DocFile> = vec![];
|
||||||
|
let mut search_indexes: Vec<SearchIndex> = vec![];
|
||||||
|
|
||||||
|
for module in &modules {
|
||||||
|
let (indexes, file) = generate_module(
|
||||||
|
config,
|
||||||
|
module,
|
||||||
|
(&modules_prefix, &modules_links),
|
||||||
|
&source,
|
||||||
|
×tamp,
|
||||||
|
);
|
||||||
|
search_indexes.extend(indexes);
|
||||||
|
output_files.push(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
output_files.extend(generate_static_assets(search_indexes));
|
||||||
|
output_files.push(generate_readme(
|
||||||
|
root,
|
||||||
|
config,
|
||||||
|
(&modules_prefix, &modules_links),
|
||||||
|
&source,
|
||||||
|
×tamp,
|
||||||
|
));
|
||||||
|
|
||||||
|
output_files
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_module(
|
||||||
|
config: &Config,
|
||||||
|
module: &CheckedModule,
|
||||||
|
(modules_prefix, modules): (&str, &Vec<DocLink>),
|
||||||
|
source: &DocLink,
|
||||||
|
timestamp: &Duration,
|
||||||
|
) -> (Vec<SearchIndex>, DocFile) {
|
||||||
|
let mut search_indexes = vec![];
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
let functions: Vec<DocFunction> = module
|
||||||
|
.ast
|
||||||
|
.definitions
|
||||||
|
.iter()
|
||||||
|
.flat_map(DocFunction::from_definition)
|
||||||
|
.sorted()
|
||||||
|
.collect();
|
||||||
|
functions
|
||||||
|
.iter()
|
||||||
|
.for_each(|function| search_indexes.push(SearchIndex::from_function(module, function)));
|
||||||
|
|
||||||
|
// Types
|
||||||
|
let types: Vec<DocType> = module
|
||||||
|
.ast
|
||||||
|
.definitions
|
||||||
|
.iter()
|
||||||
|
.flat_map(DocType::from_definition)
|
||||||
|
.sorted()
|
||||||
|
.collect();
|
||||||
|
types
|
||||||
|
.iter()
|
||||||
|
.for_each(|type_info| search_indexes.push(SearchIndex::from_type(module, type_info)));
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
let constants: Vec<DocConstant> = module
|
||||||
|
.ast
|
||||||
|
.definitions
|
||||||
|
.iter()
|
||||||
|
.flat_map(DocConstant::from_definition)
|
||||||
|
.sorted()
|
||||||
|
.collect();
|
||||||
|
constants
|
||||||
|
.iter()
|
||||||
|
.for_each(|constant| search_indexes.push(SearchIndex::from_constant(module, constant)));
|
||||||
|
|
||||||
|
// Module
|
||||||
|
search_indexes.push(SearchIndex::from_module(module));
|
||||||
|
let module = ModuleTemplate {
|
||||||
|
aiken_version: VERSION,
|
||||||
|
breadcrumbs: to_breadcrumbs(&module.name),
|
||||||
|
documentation: render_markdown(&module.ast.docs.iter().join("\n")),
|
||||||
|
modules_prefix: modules_prefix.to_string(),
|
||||||
|
modules,
|
||||||
|
project_name: &config.name,
|
||||||
|
page_title: &format!("{} - {}", module.name, config.name),
|
||||||
|
module_name: module.name.clone(),
|
||||||
|
project_version: &config.version.to_string(),
|
||||||
|
functions,
|
||||||
|
types,
|
||||||
|
constants,
|
||||||
|
source,
|
||||||
|
timestamp: timestamp.as_secs().to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
(
|
||||||
|
search_indexes,
|
||||||
|
DocFile {
|
||||||
|
path: PathBuf::from(format!("{}.html", module.module_name)),
|
||||||
|
content: module
|
||||||
|
.render()
|
||||||
|
.expect("Module documentation template rendering"),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_static_assets(search_indexes: Vec<SearchIndex>) -> Vec<DocFile> {
|
||||||
|
let mut assets: Vec<DocFile> = vec![];
|
||||||
|
|
||||||
|
assets.push(DocFile {
|
||||||
|
path: PathBuf::from("favicon.svg"),
|
||||||
|
content: std::include_str!("../templates/favicon.svg").to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
assets.push(DocFile {
|
||||||
|
path: PathBuf::from("css/atom-one-light.min.css"),
|
||||||
|
content: std::include_str!("../templates/css/atom-one-light.min.css").to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
assets.push(DocFile {
|
||||||
|
path: PathBuf::from("css/atom-one-dark.min.css"),
|
||||||
|
content: std::include_str!("../templates/css/atom-one-dark.min.css").to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
assets.push(DocFile {
|
||||||
|
path: PathBuf::from("css/index.css"),
|
||||||
|
content: std::include_str!("../templates/css/index.css").to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
assets.push(DocFile {
|
||||||
|
path: PathBuf::from("js/highlight.min.js"),
|
||||||
|
content: std::include_str!("../templates/js/highlight.min.js").to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
assets.push(DocFile {
|
||||||
|
path: PathBuf::from("js/highlightjs-aiken.js"),
|
||||||
|
content: std::include_str!("../templates/js/highlightjs-aiken.js").to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
assets.push(DocFile {
|
||||||
|
path: PathBuf::from("js/lunr.min.js"),
|
||||||
|
content: std::include_str!("../templates/js/lunr.min.js").to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
assets.push(DocFile {
|
||||||
|
path: PathBuf::from("js/index.js"),
|
||||||
|
content: std::include_str!("../templates/js/index.js").to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
assets.push(DocFile {
|
||||||
|
path: PathBuf::from("search-data.js"),
|
||||||
|
content: format!(
|
||||||
|
"window.Aiken.initSearch({});",
|
||||||
|
json::to_string(&escape_html_contents(search_indexes))
|
||||||
|
.expect("search index serialization")
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
assets
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_readme(
|
||||||
|
root: &Path,
|
||||||
|
config: &Config,
|
||||||
|
(modules_prefix, modules): (&str, &Vec<DocLink>),
|
||||||
|
source: &DocLink,
|
||||||
|
timestamp: &Duration,
|
||||||
|
) -> DocFile {
|
||||||
|
let path = PathBuf::from("index.html");
|
||||||
|
|
||||||
|
let content = std::fs::read_to_string(root.join("README.md")).unwrap_or_default();
|
||||||
|
|
||||||
|
let template = PageTemplate {
|
||||||
|
aiken_version: VERSION,
|
||||||
|
breadcrumbs: ".",
|
||||||
|
modules_prefix: modules_prefix.to_string(),
|
||||||
|
modules,
|
||||||
|
project_name: &config.name,
|
||||||
|
page_title: &config.name,
|
||||||
|
project_version: &config.version.to_string(),
|
||||||
|
content: render_markdown(&content),
|
||||||
|
source,
|
||||||
|
timestamp: ×tamp.as_secs().to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
DocFile {
|
||||||
|
path,
|
||||||
|
content: template.render().expect("Page template rendering"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_modules_links(modules: &Vec<&CheckedModule>) -> (String, Vec<DocLink>) {
|
||||||
|
let mut modules_links = vec![];
|
||||||
|
for module in modules {
|
||||||
|
let module_path = [&module.name.clone(), ".html"].concat();
|
||||||
|
modules_links.push(DocLink {
|
||||||
|
path: module_path,
|
||||||
|
name: module.name.to_string().clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
modules_links.sort();
|
||||||
|
|
||||||
|
let prefix = find_modules_prefix(&modules_links);
|
||||||
|
|
||||||
|
for module in &mut modules_links {
|
||||||
|
let name = module.name.strip_prefix(&prefix).unwrap_or_default();
|
||||||
|
module.name = name.strip_prefix('/').unwrap_or(name).to_string();
|
||||||
|
if module.name == String::new() {
|
||||||
|
module.name = "/".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(prefix, modules_links)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
|
struct SearchIndex {
|
||||||
|
doc: String,
|
||||||
|
title: String,
|
||||||
|
content: String,
|
||||||
|
url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SearchIndex {
|
||||||
|
fn from_function(module: &CheckedModule, function: &DocFunction) -> Self {
|
||||||
|
SearchIndex {
|
||||||
|
doc: module.name.to_string(),
|
||||||
|
title: function.name.to_string(),
|
||||||
|
content: format!("{}\n{}", function.signature, function.documentation),
|
||||||
|
url: format!("{}.html#{}", module.name, function.name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_type(module: &CheckedModule, type_info: &DocType) -> Self {
|
||||||
|
let constructors = type_info
|
||||||
|
.constructors
|
||||||
|
.iter()
|
||||||
|
.map(|constructor| {
|
||||||
|
let arguments = constructor
|
||||||
|
.arguments
|
||||||
|
.iter()
|
||||||
|
.map(|argument| format!("{}\n{}", argument.label, argument.documentation))
|
||||||
|
.join("\n");
|
||||||
|
format!(
|
||||||
|
"{}\n{}\n{}",
|
||||||
|
constructor.definition, constructor.documentation, arguments
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
SearchIndex {
|
||||||
|
doc: module.name.to_string(),
|
||||||
|
title: type_info.name.to_string(),
|
||||||
|
content: format!(
|
||||||
|
"{}\n{}\n{}",
|
||||||
|
type_info.definition, type_info.documentation, constructors,
|
||||||
|
),
|
||||||
|
url: format!("{}.html#{}", module.name, type_info.name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_constant(module: &CheckedModule, constant: &DocConstant) -> Self {
|
||||||
|
SearchIndex {
|
||||||
|
doc: module.name.to_string(),
|
||||||
|
title: constant.name.to_string(),
|
||||||
|
content: format!("{}\n{}", constant.definition, constant.documentation),
|
||||||
|
url: format!("{}.html#{}", module.name, constant.name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_module(module: &CheckedModule) -> Self {
|
||||||
|
SearchIndex {
|
||||||
|
doc: module.name.to_string(),
|
||||||
|
title: module.name.to_string(),
|
||||||
|
content: module.ast.docs.iter().join("\n"),
|
||||||
|
url: format!("{}.html", module.name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
struct DocFunction {
|
||||||
|
name: String,
|
||||||
|
signature: String,
|
||||||
|
documentation: String,
|
||||||
|
source_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DocFunction {
|
||||||
|
fn from_definition(def: &TypedDefinition) -> Option<Self> {
|
||||||
|
match def {
|
||||||
|
Definition::Fn(func_def) if func_def.public => Some(DocFunction {
|
||||||
|
name: func_def.name.clone(),
|
||||||
|
documentation: func_def
|
||||||
|
.doc
|
||||||
|
.as_deref()
|
||||||
|
.map(render_markdown)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
signature: format::Formatter::new()
|
||||||
|
.docs_fn_signature(
|
||||||
|
&func_def.name,
|
||||||
|
&func_def.arguments,
|
||||||
|
&func_def.return_annotation,
|
||||||
|
func_def.return_type.clone(),
|
||||||
|
)
|
||||||
|
.to_pretty_string(MAX_COLUMNS),
|
||||||
|
source_url: "#todo".to_string(),
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
struct DocConstant {
|
||||||
|
name: String,
|
||||||
|
definition: String,
|
||||||
|
documentation: String,
|
||||||
|
source_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DocConstant {
|
||||||
|
fn from_definition(def: &TypedDefinition) -> Option<Self> {
|
||||||
|
match def {
|
||||||
|
Definition::ModuleConstant(const_def) if const_def.public => Some(DocConstant {
|
||||||
|
name: const_def.name.clone(),
|
||||||
|
documentation: const_def
|
||||||
|
.doc
|
||||||
|
.as_deref()
|
||||||
|
.map(render_markdown)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
definition: format::Formatter::new()
|
||||||
|
.docs_const_expr(&const_def.name, &const_def.value)
|
||||||
|
.to_pretty_string(MAX_COLUMNS),
|
||||||
|
source_url: "#todo".to_string(),
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||||
|
struct DocType {
|
||||||
|
name: String,
|
||||||
|
definition: String,
|
||||||
|
documentation: String,
|
||||||
|
constructors: Vec<DocTypeConstructor>,
|
||||||
|
source_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DocType {
|
||||||
|
fn from_definition(def: &TypedDefinition) -> Option<Self> {
|
||||||
|
match def {
|
||||||
|
Definition::TypeAlias(info) if info.public => Some(DocType {
|
||||||
|
name: info.alias.clone(),
|
||||||
|
definition: format::Formatter::new()
|
||||||
|
.docs_type_alias(&info.alias, &info.parameters, &info.annotation)
|
||||||
|
.to_pretty_string(MAX_COLUMNS),
|
||||||
|
documentation: info.doc.as_deref().map(render_markdown).unwrap_or_default(),
|
||||||
|
constructors: vec![],
|
||||||
|
source_url: "#todo".to_string(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
Definition::DataType(info) if info.public && !info.opaque => Some(DocType {
|
||||||
|
name: info.name.clone(),
|
||||||
|
definition: format::Formatter::new()
|
||||||
|
.docs_data_type(
|
||||||
|
&info.name,
|
||||||
|
&info.parameters,
|
||||||
|
&info.constructors,
|
||||||
|
&info.location,
|
||||||
|
)
|
||||||
|
.to_pretty_string(MAX_COLUMNS),
|
||||||
|
documentation: info.doc.as_deref().map(render_markdown).unwrap_or_default(),
|
||||||
|
constructors: info
|
||||||
|
.constructors
|
||||||
|
.iter()
|
||||||
|
.map(DocTypeConstructor::from_record_constructor)
|
||||||
|
.collect(),
|
||||||
|
source_url: "#todo".to_string(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
Definition::DataType(info) if info.public && info.opaque => Some(DocType {
|
||||||
|
name: info.name.clone(),
|
||||||
|
definition: format::Formatter::new()
|
||||||
|
.docs_opaque_data_type(&info.name, &info.parameters, &info.location)
|
||||||
|
.to_pretty_string(MAX_COLUMNS),
|
||||||
|
documentation: info.doc.as_deref().map(render_markdown).unwrap_or_default(),
|
||||||
|
constructors: vec![],
|
||||||
|
source_url: "#todo".to_string(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||||
|
struct DocTypeConstructor {
|
||||||
|
definition: String,
|
||||||
|
documentation: String,
|
||||||
|
arguments: Vec<DocTypeConstructorArg>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DocTypeConstructor {
|
||||||
|
fn from_record_constructor(constructor: &RecordConstructor<Arc<Type>>) -> Self {
|
||||||
|
DocTypeConstructor {
|
||||||
|
definition: format::Formatter::new()
|
||||||
|
.docs_record_constructor(constructor)
|
||||||
|
.to_pretty_string(MAX_COLUMNS),
|
||||||
|
documentation: constructor
|
||||||
|
.doc
|
||||||
|
.as_deref()
|
||||||
|
.map(render_markdown)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
arguments: constructor
|
||||||
|
.arguments
|
||||||
|
.iter()
|
||||||
|
.filter_map(DocTypeConstructorArg::from_record_constructor_arg)
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||||
|
struct DocTypeConstructorArg {
|
||||||
|
label: String,
|
||||||
|
documentation: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DocTypeConstructorArg {
|
||||||
|
fn from_record_constructor_arg(arg: &RecordConstructorArg<Arc<Type>>) -> Option<Self> {
|
||||||
|
arg.label.as_ref().map(|label| DocTypeConstructorArg {
|
||||||
|
label: label.clone(),
|
||||||
|
documentation: arg.doc.as_deref().map(render_markdown).unwrap_or_default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------ Extra Helpers
|
||||||
|
|
||||||
|
fn render_markdown(text: &str) -> String {
|
||||||
|
let mut s = String::with_capacity(text.len() * 3 / 2);
|
||||||
|
let p = markdown::Parser::new_ext(text, markdown::Options::all());
|
||||||
|
markdown::html::push_html(&mut s, p);
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
fn escape_html_contents(indexes: Vec<SearchIndex>) -> Vec<SearchIndex> {
|
||||||
|
fn escape_html_content(it: String) -> String {
|
||||||
|
it.replace('&', "&")
|
||||||
|
.replace('<', "<")
|
||||||
|
.replace('>', ">")
|
||||||
|
.replace('\"', """)
|
||||||
|
.replace('\'', "'")
|
||||||
|
}
|
||||||
|
|
||||||
|
indexes
|
||||||
|
.into_iter()
|
||||||
|
.map(|idx| SearchIndex {
|
||||||
|
doc: idx.doc,
|
||||||
|
title: idx.title,
|
||||||
|
content: escape_html_content(idx.content),
|
||||||
|
url: idx.url,
|
||||||
|
})
|
||||||
|
.collect::<Vec<SearchIndex>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_timestamp() -> Duration {
|
||||||
|
SystemTime::now()
|
||||||
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
|
.expect("get current timestamp")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_modules_prefix(modules: &[DocLink]) -> String {
|
||||||
|
modules
|
||||||
|
.iter()
|
||||||
|
.fold(None, |previous_prefix, module| {
|
||||||
|
let prefix = module
|
||||||
|
.name
|
||||||
|
.split('/')
|
||||||
|
.next()
|
||||||
|
.unwrap_or_default()
|
||||||
|
.to_string();
|
||||||
|
match previous_prefix {
|
||||||
|
None if prefix != module.name => Some(prefix),
|
||||||
|
Some(..) if Some(prefix) == previous_prefix => previous_prefix,
|
||||||
|
_ => Some(String::new()),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn find_modules_prefix_test() {
|
||||||
|
assert_eq!(find_modules_prefix(&[]), "".to_string());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
find_modules_prefix(&[DocLink {
|
||||||
|
name: "aiken/list".to_string(),
|
||||||
|
path: String::new()
|
||||||
|
}]),
|
||||||
|
"aiken".to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
find_modules_prefix(&[DocLink {
|
||||||
|
name: "my_module".to_string(),
|
||||||
|
path: String::new()
|
||||||
|
}]),
|
||||||
|
"".to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
find_modules_prefix(&[
|
||||||
|
DocLink {
|
||||||
|
name: "aiken/list".to_string(),
|
||||||
|
path: String::new()
|
||||||
|
},
|
||||||
|
DocLink {
|
||||||
|
name: "aiken/byte_array".to_string(),
|
||||||
|
path: String::new(),
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
"aiken".to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
find_modules_prefix(&[
|
||||||
|
DocLink {
|
||||||
|
name: "aiken/list".to_string(),
|
||||||
|
path: String::new()
|
||||||
|
},
|
||||||
|
DocLink {
|
||||||
|
name: "foo/byte_array".to_string(),
|
||||||
|
path: String::new(),
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
"".to_string()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_breadcrumbs(path: &str) -> String {
|
||||||
|
let breadcrumbs = path
|
||||||
|
.strip_prefix('/')
|
||||||
|
.unwrap_or(path)
|
||||||
|
.split('/')
|
||||||
|
.skip(1)
|
||||||
|
.map(|_| "..")
|
||||||
|
.join("/");
|
||||||
|
if breadcrumbs.is_empty() {
|
||||||
|
".".to_string()
|
||||||
|
} else {
|
||||||
|
breadcrumbs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn to_breadcrumbs_test() {
|
||||||
|
// Pages
|
||||||
|
assert_eq!(to_breadcrumbs("a.html"), ".");
|
||||||
|
assert_eq!(to_breadcrumbs("/a.html"), ".");
|
||||||
|
assert_eq!(to_breadcrumbs("/a/b.html"), "..");
|
||||||
|
assert_eq!(to_breadcrumbs("/a/b/c.html"), "../..");
|
||||||
|
|
||||||
|
// Modules
|
||||||
|
assert_eq!(to_breadcrumbs("a"), ".");
|
||||||
|
assert_eq!(to_breadcrumbs("a/b"), "..");
|
||||||
|
assert_eq!(to_breadcrumbs("a/b/c"), "../..");
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
pub mod docs;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod format;
|
pub mod format;
|
||||||
pub mod module;
|
pub mod module;
|
||||||
|
@ -7,6 +8,7 @@ pub mod pretty;
|
||||||
pub mod script;
|
pub mod script;
|
||||||
pub mod telemetry;
|
pub mod telemetry;
|
||||||
|
|
||||||
|
use crate::module::{CERT, MINT, SPEND, VALIDATOR_NAMES, WITHDRAW};
|
||||||
use aiken_lang::{
|
use aiken_lang::{
|
||||||
ast::{Definition, Function, ModuleKind, TypedDataType, TypedDefinition, TypedFunction},
|
ast::{Definition, Function, ModuleKind, TypedDataType, TypedDefinition, TypedFunction},
|
||||||
builder::{DataTypeKey, FunctionAccessKey},
|
builder::{DataTypeKey, FunctionAccessKey},
|
||||||
|
@ -50,12 +52,6 @@ pub struct Source {
|
||||||
pub kind: ModuleKind,
|
pub kind: ModuleKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const SPEND: &str = "spend";
|
|
||||||
pub const CERT: &str = "cert";
|
|
||||||
pub const MINT: &str = "mint";
|
|
||||||
pub const WITHDRAWL: &str = "withdrawl";
|
|
||||||
pub const VALIDATOR_NAMES: [&str; 4] = [SPEND, CERT, MINT, WITHDRAWL];
|
|
||||||
|
|
||||||
pub struct Project<T>
|
pub struct Project<T>
|
||||||
where
|
where
|
||||||
T: EventListener,
|
T: EventListener,
|
||||||
|
@ -102,6 +98,35 @@ where
|
||||||
self.compile(options)
|
self.compile(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn docs(&mut self, destination: Option<PathBuf>) -> Result<(), Error> {
|
||||||
|
self.event_listener
|
||||||
|
.handle_event(Event::BuildingDocumentation {
|
||||||
|
root: self.root.clone(),
|
||||||
|
name: self.config.name.clone(),
|
||||||
|
version: self.config.version.clone(),
|
||||||
|
});
|
||||||
|
self.read_source_files()?;
|
||||||
|
|
||||||
|
let destination = destination.unwrap_or_else(|| self.root.join("doc"));
|
||||||
|
let mut parsed_modules = self.parse_sources()?;
|
||||||
|
for (_, module) in parsed_modules.iter_mut() {
|
||||||
|
module.attach_doc_and_module_comments();
|
||||||
|
}
|
||||||
|
let checked_modules = self.type_check(parsed_modules)?;
|
||||||
|
self.event_listener.handle_event(Event::GeneratingDocFiles {
|
||||||
|
output_path: destination.clone(),
|
||||||
|
});
|
||||||
|
let doc_files =
|
||||||
|
docs::generate_all(&self.root, &self.config, checked_modules.values().collect());
|
||||||
|
for file in doc_files {
|
||||||
|
let path = destination.join(file.path);
|
||||||
|
fs::create_dir_all(path.parent().unwrap())?;
|
||||||
|
fs::write(&path, file.content)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn check(
|
pub fn check(
|
||||||
&mut self,
|
&mut self,
|
||||||
skip_tests: bool,
|
skip_tests: bool,
|
||||||
|
@ -130,18 +155,9 @@ where
|
||||||
version: self.config.version.clone(),
|
version: self.config.version.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
self.event_listener.handle_event(Event::ParsingProjectFiles);
|
|
||||||
|
|
||||||
self.read_source_files()?;
|
self.read_source_files()?;
|
||||||
|
|
||||||
let parsed_modules = self.parse_sources()?;
|
let parsed_modules = self.parse_sources()?;
|
||||||
|
let mut checked_modules = self.type_check(parsed_modules)?;
|
||||||
let processing_sequence = parsed_modules.sequence()?;
|
|
||||||
|
|
||||||
self.event_listener.handle_event(Event::TypeChecking);
|
|
||||||
|
|
||||||
let mut checked_modules = self.type_check(parsed_modules, processing_sequence)?;
|
|
||||||
|
|
||||||
let validators = self.validate_validators(&mut checked_modules)?;
|
let validators = self.validate_validators(&mut checked_modules)?;
|
||||||
|
|
||||||
match options.code_gen_mode {
|
match options.code_gen_mode {
|
||||||
|
@ -203,6 +219,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_sources(&mut self) -> Result<ParsedModules, Error> {
|
fn parse_sources(&mut self) -> Result<ParsedModules, Error> {
|
||||||
|
self.event_listener.handle_event(Event::ParsingProjectFiles);
|
||||||
|
|
||||||
let mut errors = Vec::new();
|
let mut errors = Vec::new();
|
||||||
let mut parsed_modules = HashMap::with_capacity(self.sources.len());
|
let mut parsed_modules = HashMap::with_capacity(self.sources.len());
|
||||||
|
|
||||||
|
@ -214,7 +232,7 @@ where
|
||||||
} in self.sources.drain(0..)
|
} in self.sources.drain(0..)
|
||||||
{
|
{
|
||||||
match aiken_lang::parser::module(&code, kind) {
|
match aiken_lang::parser::module(&code, kind) {
|
||||||
Ok((mut ast, _)) => {
|
Ok((mut ast, extra)) => {
|
||||||
// Store the name
|
// Store the name
|
||||||
ast.name = name.clone();
|
ast.name = name.clone();
|
||||||
|
|
||||||
|
@ -224,6 +242,7 @@ where
|
||||||
code,
|
code,
|
||||||
name,
|
name,
|
||||||
path,
|
path,
|
||||||
|
extra,
|
||||||
package: self.config.name.clone(),
|
package: self.config.name.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -260,11 +279,9 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_check(
|
fn type_check(&mut self, mut parsed_modules: ParsedModules) -> Result<CheckedModules, Error> {
|
||||||
&mut self,
|
self.event_listener.handle_event(Event::TypeChecking);
|
||||||
mut parsed_modules: ParsedModules,
|
let processing_sequence = parsed_modules.sequence()?;
|
||||||
processing_sequence: Vec<String>,
|
|
||||||
) -> Result<CheckedModules, Error> {
|
|
||||||
let mut modules = HashMap::with_capacity(parsed_modules.len() + 1);
|
let mut modules = HashMap::with_capacity(parsed_modules.len() + 1);
|
||||||
|
|
||||||
for name in processing_sequence {
|
for name in processing_sequence {
|
||||||
|
@ -273,6 +290,7 @@ where
|
||||||
path,
|
path,
|
||||||
code,
|
code,
|
||||||
kind,
|
kind,
|
||||||
|
extra,
|
||||||
// TODO: come back and figure out where to use this
|
// TODO: come back and figure out where to use this
|
||||||
package: _package,
|
package: _package,
|
||||||
ast,
|
ast,
|
||||||
|
@ -311,7 +329,7 @@ where
|
||||||
name.clone(),
|
name.clone(),
|
||||||
CheckedModule {
|
CheckedModule {
|
||||||
kind,
|
kind,
|
||||||
// extra,
|
extra,
|
||||||
name,
|
name,
|
||||||
code,
|
code,
|
||||||
ast,
|
ast,
|
||||||
|
@ -351,7 +369,7 @@ where
|
||||||
|
|
||||||
// depending on name, validate the minimum number of arguments
|
// depending on name, validate the minimum number of arguments
|
||||||
// if too low, push a new error on to errors
|
// if too low, push a new error on to errors
|
||||||
if [MINT, CERT, WITHDRAWL].contains(&func_def.name.as_str())
|
if [MINT, CERT, WITHDRAW].contains(&func_def.name.as_str())
|
||||||
&& func_def.arguments.len() < 2
|
&& func_def.arguments.len() < 2
|
||||||
{
|
{
|
||||||
errors.push(Error::WrongValidatorArity {
|
errors.push(Error::WrongValidatorArity {
|
||||||
|
|
|
@ -4,7 +4,10 @@ use std::{
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
};
|
};
|
||||||
|
|
||||||
use aiken_lang::ast::{ModuleKind, TypedModule, UntypedModule};
|
use aiken_lang::{
|
||||||
|
ast::{DataType, Definition, ModuleKind, TypedModule, UntypedModule},
|
||||||
|
parser::extra::{comments_before, Comment, ModuleExtra},
|
||||||
|
};
|
||||||
use petgraph::{algo, graph::NodeIndex, Direction, Graph};
|
use petgraph::{algo, graph::NodeIndex, Direction, Graph};
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
@ -17,7 +20,7 @@ pub struct ParsedModule {
|
||||||
pub kind: ModuleKind,
|
pub kind: ModuleKind,
|
||||||
pub package: String,
|
pub package: String,
|
||||||
pub ast: UntypedModule,
|
pub ast: UntypedModule,
|
||||||
// extra: ModuleExtra,
|
pub extra: ModuleExtra,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParsedModule {
|
impl ParsedModule {
|
||||||
|
@ -33,6 +36,55 @@ impl ParsedModule {
|
||||||
|
|
||||||
(name, deps)
|
(name, deps)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn attach_doc_and_module_comments(&mut self) {
|
||||||
|
// Module Comments
|
||||||
|
self.ast.docs = self
|
||||||
|
.extra
|
||||||
|
.module_comments
|
||||||
|
.iter()
|
||||||
|
.map(|span| {
|
||||||
|
Comment::from((span, self.code.as_str()))
|
||||||
|
.content
|
||||||
|
.to_string()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Order definitions to avoid dissociating doc comments from them
|
||||||
|
let mut definitions: Vec<_> = self.ast.definitions.iter_mut().collect();
|
||||||
|
definitions.sort_by(|a, b| a.location().start.cmp(&b.location().start));
|
||||||
|
|
||||||
|
// Doc Comments
|
||||||
|
let mut doc_comments = self.extra.doc_comments.iter().peekable();
|
||||||
|
for def in &mut definitions {
|
||||||
|
let docs: Vec<&str> =
|
||||||
|
comments_before(&mut doc_comments, def.location().start, &self.code);
|
||||||
|
if !docs.is_empty() {
|
||||||
|
let doc = docs.join("\n");
|
||||||
|
def.put_doc(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Definition::DataType(DataType { constructors, .. }) = def {
|
||||||
|
for constructor in constructors {
|
||||||
|
let docs: Vec<&str> =
|
||||||
|
comments_before(&mut doc_comments, constructor.location.start, &self.code);
|
||||||
|
if !docs.is_empty() {
|
||||||
|
let doc = docs.join("\n");
|
||||||
|
constructor.put_doc(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
for argument in constructor.arguments.iter_mut() {
|
||||||
|
let docs: Vec<&str> =
|
||||||
|
comments_before(&mut doc_comments, argument.location.start, &self.code);
|
||||||
|
if !docs.is_empty() {
|
||||||
|
let doc = docs.join("\n");
|
||||||
|
argument.put_doc(doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ParsedModules(HashMap<String, ParsedModule>);
|
pub struct ParsedModules(HashMap<String, ParsedModule>);
|
||||||
|
@ -155,6 +207,12 @@ fn find_cycle(
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const SPEND: &str = "spend";
|
||||||
|
pub const CERT: &str = "cert";
|
||||||
|
pub const MINT: &str = "mint";
|
||||||
|
pub const WITHDRAW: &str = "withdraw";
|
||||||
|
pub const VALIDATOR_NAMES: [&str; 4] = [SPEND, CERT, MINT, WITHDRAW];
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CheckedModule {
|
pub struct CheckedModule {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
@ -162,7 +220,7 @@ pub struct CheckedModule {
|
||||||
pub input_path: PathBuf,
|
pub input_path: PathBuf,
|
||||||
pub kind: ModuleKind,
|
pub kind: ModuleKind,
|
||||||
pub ast: TypedModule,
|
pub ast: TypedModule,
|
||||||
// pub extra: ModuleExtra,
|
pub extra: ModuleExtra,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
@ -11,8 +11,16 @@ pub enum Event {
|
||||||
version: String,
|
version: String,
|
||||||
root: PathBuf,
|
root: PathBuf,
|
||||||
},
|
},
|
||||||
|
BuildingDocumentation {
|
||||||
|
name: String,
|
||||||
|
version: String,
|
||||||
|
root: PathBuf,
|
||||||
|
},
|
||||||
ParsingProjectFiles,
|
ParsingProjectFiles,
|
||||||
TypeChecking,
|
TypeChecking,
|
||||||
|
GeneratingDocFiles {
|
||||||
|
output_path: PathBuf,
|
||||||
|
},
|
||||||
GeneratingUPLC {
|
GeneratingUPLC {
|
||||||
output_path: PathBuf,
|
output_path: PathBuf,
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,262 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||||
|
<title>{{ page_title }}</title>
|
||||||
|
<meta name="theme-color" content="#eff1f5" media="(prefers-color-scheme: light)"/>
|
||||||
|
<meta name="theme-color" content="#1e1e2e" media="(prefers-color-scheme: dark)"/>
|
||||||
|
<link rel="icon" type="image/svg+xml" sizes="any" href="{{ breadcrumbs }}/favicon.svg"/>
|
||||||
|
<link rel="stylesheet" href="{{ breadcrumbs }}/css/index.css?v={{ aiken_version }}" type="text/css"/>
|
||||||
|
<link id="syntax-theme" rel="stylesheet" href="{{ breadcrumbs }}/css/atom-one-light.min.css?v={{ aiken_version }}"/>
|
||||||
|
</head>
|
||||||
|
<body class="prewrap-off theme-light drawer-closed">
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
window.breadcrumbs = '{{ breadcrumbs }}';
|
||||||
|
const aikenConfig = {
|
||||||
|
theme: {
|
||||||
|
values: (() => {
|
||||||
|
const dark = {
|
||||||
|
value: "dark",
|
||||||
|
label: "Switch to light mode",
|
||||||
|
icons: ["moon"],
|
||||||
|
};
|
||||||
|
const light = {
|
||||||
|
value: "light",
|
||||||
|
label: "Switch to dark mode",
|
||||||
|
icons: ["sun"],
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||||
|
? [dark, light]
|
||||||
|
: [light, dark]
|
||||||
|
).map((item, index) => {
|
||||||
|
item.icons.push(`toggle-${0 === index ? "left" : "right"}`);
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
})(),
|
||||||
|
|
||||||
|
update: () => "light" === Aiken.getProperty("theme") ? "dark" : "light",
|
||||||
|
|
||||||
|
callback: function(value) {
|
||||||
|
const syntaxThemes = {
|
||||||
|
dark: "atom-one-dark",
|
||||||
|
light: "atom-one-light",
|
||||||
|
};
|
||||||
|
const syntaxTheme = document.querySelector("#syntax-theme");
|
||||||
|
const hrefParts = syntaxTheme.href.match(
|
||||||
|
/^(.*?)([^/\\#?]+?)((?:\.min)?\.css.*)$/i
|
||||||
|
);
|
||||||
|
if (syntaxThemes[value] !== hrefParts[2]) {
|
||||||
|
hrefParts[2] = syntaxThemes[value];
|
||||||
|
hrefParts.shift();
|
||||||
|
syntaxTheme.href = hrefParts.join("");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
prewrap: {
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
value: "off",
|
||||||
|
label: "Switch to line-wrapped snippets",
|
||||||
|
icons: ["more-horizontal", "toggle-left"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "on",
|
||||||
|
label: "Switch to non-wrapped snippets",
|
||||||
|
icons: ["more-vertical", "toggle-right"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
update: () => "off" === Aiken.getProperty("prewrap") ? "on" : "off",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/* Initialise options before any content loads */
|
||||||
|
void function() {
|
||||||
|
for (const property in aikenConfig) {
|
||||||
|
const name = `Aiken.${property}`;
|
||||||
|
|
||||||
|
let value;
|
||||||
|
|
||||||
|
try {
|
||||||
|
value = localStorage.getItem(name);
|
||||||
|
if (value.startsWith('"') && value.endsWith('"')) {
|
||||||
|
localStorage.setItem(name, value.slice(1, value.length - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (_error) {}
|
||||||
|
|
||||||
|
const defaultValue = aikenConfig[property].values[0].value;
|
||||||
|
try {
|
||||||
|
value = localStorage.getItem(name);
|
||||||
|
}
|
||||||
|
catch(_error) {}
|
||||||
|
if (-1 < [null, undefined].indexOf(value)) {
|
||||||
|
value = defaultValue;
|
||||||
|
}
|
||||||
|
const bodyClasses = document.body.classList;
|
||||||
|
bodyClasses.remove(`${property}-${defaultValue}`);
|
||||||
|
bodyClasses.add(`${property}-${value}`);
|
||||||
|
try {
|
||||||
|
aikenConfig[property].callback(value);
|
||||||
|
}
|
||||||
|
catch(_error) {}
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<header class="page-header">
|
||||||
|
<button class="sidebar-toggle" tabindex="0">
|
||||||
|
<svg class="label label-closed icon icon-menu" alt="Open Menu" title="Open Menu"><use xlink:href="#icon-menu"></use></svg>
|
||||||
|
<svg class="label label-open icon icon-x-circle" alt="Close Menu" title="Close Menu"><use xlink:href="#icon-x-circle"></use></svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<a href="{{ breadcrumbs }}/">{{ project_name }}</a>
|
||||||
|
<span id="project-version">
|
||||||
|
<span>v{{ project_version }} </span>
|
||||||
|
</span>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
if ("undefined" !== typeof versionNodes) {
|
||||||
|
const currentVersion = "v{{ project_version }}";
|
||||||
|
if (! versionNodes.find(element => element.version === currentVersion)) {
|
||||||
|
versionNodes.unshift({ version: currentVersion, url: "#" });
|
||||||
|
}
|
||||||
|
document.querySelector("#project-version").innerHTML =
|
||||||
|
versionNodes.reduce(
|
||||||
|
(acc, element) => {
|
||||||
|
const status =
|
||||||
|
currentVersion === element.version ? "selected disabled" : "";
|
||||||
|
return `
|
||||||
|
${acc}
|
||||||
|
<option value="${element.url}" ${status}>
|
||||||
|
${element.version}
|
||||||
|
</option>
|
||||||
|
`;
|
||||||
|
},
|
||||||
|
`
|
||||||
|
<form autocomplete="off">
|
||||||
|
<select onchange="window.location.href = this.value">
|
||||||
|
`
|
||||||
|
) + `
|
||||||
|
</select>
|
||||||
|
<svg class="icon icon-chevrons-down"><use xlink:href="#icon-chevrons-down"></use></svg>
|
||||||
|
</form>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</h2>
|
||||||
|
<div class="search">
|
||||||
|
<div class="search-input-wrap">
|
||||||
|
<input type="text" id="search-input" class="search-input" tabindex="0" aria-label="Search {{ project_name }}" autocomplete="off">
|
||||||
|
<label for="search-input" class="search-label"><svg viewBox="0 0 24 24" class="search-icon"><use xlink:href="#icon-svg-search"></use></svg></label>
|
||||||
|
</div>
|
||||||
|
<div id="search-results" class="search-results"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="search-nav-button" id="search-nav-button" tabindex="0">
|
||||||
|
<svg class="label icon icon-x-circle" alt="Open Search" title="Open Search"><use xlink:href="#icon-svg-search"></use></svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="page">
|
||||||
|
<nav class="sidebar">
|
||||||
|
<button class="sidebar-toggle" tabindex="1">
|
||||||
|
<svg class="label icon icon-x-circle" alt="Close Menu" title="Close Menu"><use xlink:href="#icon-x-circle"></use></svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{% if !source.is_empty() %}
|
||||||
|
<h2>Source code</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="{{ source.path }}">{{ source.name }}</a></li>
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<h2>Modules</h2>
|
||||||
|
{% if !modules_prefix.is_empty() %}
|
||||||
|
<h3 class="modules-prefix">{{ modules_prefix }}/</h3>
|
||||||
|
{% endif %}
|
||||||
|
<ul>
|
||||||
|
{% for module in modules %}
|
||||||
|
<li><a href="{{ breadcrumbs }}/{{ module.path }}">
|
||||||
|
{% if self.is_current_module(module) %}
|
||||||
|
<strong>{{ module.name }}</strong>
|
||||||
|
{% else %}
|
||||||
|
{{ module.name }}
|
||||||
|
{% endif %}
|
||||||
|
</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% block sidebar_content %}{% endblock %}
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="content">
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
<div class="search-overlay"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<svg class="svg-lib" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs>
|
||||||
|
<symbol id="icon-chevrons-down" viewBox="0 0 24 24"><path d="M6.293 13.707l5 5c0.391 0.391 1.024 0.391 1.414 0l5-5c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-4.293 4.293-4.293-4.293c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414zM6.293 6.707l5 5c0.391 0.391 1.024 0.391 1.414 0l5-5c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-4.293 4.293-4.293-4.293c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414z"></path></symbol>
|
||||||
|
|
||||||
|
<symbol id="icon-menu" viewBox="0 0 24 24"><path d="M3 13h18c0.552 0 1-0.448 1-1s-0.448-1-1-1h-18c-0.552 0-1 0.448-1 1s0.448 1 1 1zM3 7h18c0.552 0 1-0.448 1-1s-0.448-1-1-1h-18c-0.552 0-1 0.448-1 1s0.448 1 1 1zM3 19h18c0.552 0 1-0.448 1-1s-0.448-1-1-1h-18c-0.552 0-1 0.448-1 1s0.448 1 1 1z"></path></symbol>
|
||||||
|
|
||||||
|
<symbol id="icon-moon" viewBox="0 0 24 24"><path d="M21.996 12.882c0.022-0.233-0.038-0.476-0.188-0.681-0.325-0.446-0.951-0.544-1.397-0.219-0.95 0.693-2.060 1.086-3.188 1.162-1.368 0.092-2.765-0.283-3.95-1.158-1.333-0.985-2.139-2.415-2.367-3.935s0.124-3.124 1.109-4.456c0.142-0.191 0.216-0.435 0.191-0.691-0.053-0.55-0.542-0.952-1.092-0.898-2.258 0.22-4.314 1.18-5.895 2.651-1.736 1.615-2.902 3.847-3.137 6.386-0.254 2.749 0.631 5.343 2.266 7.311s4.022 3.313 6.772 3.567 5.343-0.631 7.311-2.266 3.313-4.022 3.567-6.772zM19.567 14.674c-0.49 1.363-1.335 2.543-2.416 3.441-1.576 1.309-3.648 2.016-5.848 1.813s-4.108-1.278-5.417-2.854-2.016-3.648-1.813-5.848c0.187-2.032 1.117-3.814 2.507-5.106 0.782-0.728 1.71-1.3 2.731-1.672-0.456 1.264-0.577 2.606-0.384 3.899 0.303 2.023 1.38 3.934 3.156 5.247 1.578 1.167 3.448 1.668 5.272 1.545 0.752-0.050 1.496-0.207 2.21-0.465z"></path></symbol>
|
||||||
|
|
||||||
|
<symbol id="icon-more-horizontal" viewBox="0 0 24 24"><path d="M14 12c0-0.552-0.225-1.053-0.586-1.414s-0.862-0.586-1.414-0.586-1.053 0.225-1.414 0.586-0.586 0.862-0.586 1.414 0.225 1.053 0.586 1.414 0.862 0.586 1.414 0.586 1.053-0.225 1.414-0.586 0.586-0.862 0.586-1.414zM21 12c0-0.552-0.225-1.053-0.586-1.414s-0.862-0.586-1.414-0.586-1.053 0.225-1.414 0.586-0.586 0.862-0.586 1.414 0.225 1.053 0.586 1.414 0.862 0.586 1.414 0.586 1.053-0.225 1.414-0.586 0.586-0.862 0.586-1.414zM7 12c0-0.552-0.225-1.053-0.586-1.414s-0.862-0.586-1.414-0.586-1.053 0.225-1.414 0.586-0.586 0.862-0.586 1.414 0.225 1.053 0.586 1.414 0.862 0.586 1.414 0.586 1.053-0.225 1.414-0.586 0.586-0.862 0.586-1.414z"></path></symbol>
|
||||||
|
|
||||||
|
<symbol id="icon-more-vertical" viewBox="0 0 24 24"><path d="M14 12c0-0.552-0.225-1.053-0.586-1.414s-0.862-0.586-1.414-0.586-1.053 0.225-1.414 0.586-0.586 0.862-0.586 1.414 0.225 1.053 0.586 1.414 0.862 0.586 1.414 0.586 1.053-0.225 1.414-0.586 0.586-0.862 0.586-1.414zM14 5c0-0.552-0.225-1.053-0.586-1.414s-0.862-0.586-1.414-0.586-1.053 0.225-1.414 0.586-0.586 0.862-0.586 1.414 0.225 1.053 0.586 1.414 0.862 0.586 1.414 0.586 1.053-0.225 1.414-0.586 0.586-0.862 0.586-1.414zM14 19c0-0.552-0.225-1.053-0.586-1.414s-0.862-0.586-1.414-0.586-1.053 0.225-1.414 0.586-0.586 0.862-0.586 1.414 0.225 1.053 0.586 1.414 0.862 0.586 1.414 0.586 1.053-0.225 1.414-0.586 0.586-0.862 0.586-1.414z"></path></symbol>
|
||||||
|
|
||||||
|
<symbol id="icon-star" viewBox="0 0 24 24"><path d="M12.897 1.557c-0.092-0.189-0.248-0.352-0.454-0.454-0.495-0.244-1.095-0.041-1.339 0.454l-2.858 5.789-6.391 0.935c-0.208 0.029-0.411 0.127-0.571 0.291-0.386 0.396-0.377 1.029 0.018 1.414l4.623 4.503-1.091 6.362c-0.036 0.207-0.006 0.431 0.101 0.634 0.257 0.489 0.862 0.677 1.351 0.42l5.714-3.005 5.715 3.005c0.186 0.099 0.408 0.139 0.634 0.101 0.544-0.093 0.91-0.61 0.817-1.155l-1.091-6.362 4.623-4.503c0.151-0.146 0.259-0.344 0.292-0.572 0.080-0.546-0.298-1.054-0.845-1.134l-6.39-0.934zM12 4.259l2.193 4.444c0.151 0.305 0.436 0.499 0.752 0.547l4.906 0.717-3.549 3.457c-0.244 0.238-0.341 0.569-0.288 0.885l0.837 4.883-4.386-2.307c-0.301-0.158-0.647-0.148-0.931 0l-4.386 2.307 0.837-4.883c0.058-0.336-0.059-0.661-0.288-0.885l-3.549-3.457 4.907-0.718c0.336-0.049 0.609-0.26 0.752-0.546z"></path></symbol>
|
||||||
|
|
||||||
|
<symbol id="icon-sun" viewBox="0 0 24 24"><path d="M18 12c0-1.657-0.673-3.158-1.757-4.243s-2.586-1.757-4.243-1.757-3.158 0.673-4.243 1.757-1.757 2.586-1.757 4.243 0.673 3.158 1.757 4.243 2.586 1.757 4.243 1.757 3.158-0.673 4.243-1.757 1.757-2.586 1.757-4.243zM16 12c0 1.105-0.447 2.103-1.172 2.828s-1.723 1.172-2.828 1.172-2.103-0.447-2.828-1.172-1.172-1.723-1.172-2.828 0.447-2.103 1.172-2.828 1.723-1.172 2.828-1.172 2.103 0.447 2.828 1.172 1.172 1.723 1.172 2.828zM11 1v2c0 0.552 0.448 1 1 1s1-0.448 1-1v-2c0-0.552-0.448-1-1-1s-1 0.448-1 1zM11 21v2c0 0.552 0.448 1 1 1s1-0.448 1-1v-2c0-0.552-0.448-1-1-1s-1 0.448-1 1zM3.513 4.927l1.42 1.42c0.391 0.391 1.024 0.391 1.414 0s0.391-1.024 0-1.414l-1.42-1.42c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414zM17.653 19.067l1.42 1.42c0.391 0.391 1.024 0.391 1.414 0s0.391-1.024 0-1.414l-1.42-1.42c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414zM1 13h2c0.552 0 1-0.448 1-1s-0.448-1-1-1h-2c-0.552 0-1 0.448-1 1s0.448 1 1 1zM21 13h2c0.552 0 1-0.448 1-1s-0.448-1-1-1h-2c-0.552 0-1 0.448-1 1s0.448 1 1 1zM4.927 20.487l1.42-1.42c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-1.42 1.42c-0.391 0.391-0.391 1.024 0 1.414s1.024 0.391 1.414 0zM19.067 6.347l1.42-1.42c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-1.42 1.42c-0.391 0.391-0.391 1.024 0 1.414s1.024 0.391 1.414 0z"></path></symbol>
|
||||||
|
|
||||||
|
<symbol id="icon-toggle-left" viewBox="0 0 24 24"><path d="M8 4c-2.209 0-4.21 0.897-5.657 2.343s-2.343 3.448-2.343 5.657 0.897 4.21 2.343 5.657 3.448 2.343 5.657 2.343h8c2.209 0 4.21-0.897 5.657-2.343s2.343-3.448 2.343-5.657-0.897-4.21-2.343-5.657-3.448-2.343-5.657-2.343zM8 6h8c1.657 0 3.156 0.67 4.243 1.757s1.757 2.586 1.757 4.243-0.67 3.156-1.757 4.243-2.586 1.757-4.243 1.757h-8c-1.657 0-3.156-0.67-4.243-1.757s-1.757-2.586-1.757-4.243 0.67-3.156 1.757-4.243 2.586-1.757 4.243-1.757zM12 12c0-1.104-0.449-2.106-1.172-2.828s-1.724-1.172-2.828-1.172-2.106 0.449-2.828 1.172-1.172 1.724-1.172 2.828 0.449 2.106 1.172 2.828 1.724 1.172 2.828 1.172 2.106-0.449 2.828-1.172 1.172-1.724 1.172-2.828zM10 12c0 0.553-0.223 1.051-0.586 1.414s-0.861 0.586-1.414 0.586-1.051-0.223-1.414-0.586-0.586-0.861-0.586-1.414 0.223-1.051 0.586-1.414 0.861-0.586 1.414-0.586 1.051 0.223 1.414 0.586 0.586 0.861 0.586 1.414z"></path></symbol>
|
||||||
|
|
||||||
|
<symbol id="icon-toggle-right" viewBox="0 0 24 24"><path d="M8 4c-2.209 0-4.21 0.897-5.657 2.343s-2.343 3.448-2.343 5.657 0.897 4.21 2.343 5.657 3.448 2.343 5.657 2.343h8c2.209 0 4.21-0.897 5.657-2.343s2.343-3.448 2.343-5.657-0.897-4.21-2.343-5.657-3.448-2.343-5.657-2.343zM8 6h8c1.657 0 3.156 0.67 4.243 1.757s1.757 2.586 1.757 4.243-0.67 3.156-1.757 4.243-2.586 1.757-4.243 1.757h-8c-1.657 0-3.156-0.67-4.243-1.757s-1.757-2.586-1.757-4.243 0.67-3.156 1.757-4.243 2.586-1.757 4.243-1.757zM20 12c0-1.104-0.449-2.106-1.172-2.828s-1.724-1.172-2.828-1.172-2.106 0.449-2.828 1.172-1.172 1.724-1.172 2.828 0.449 2.106 1.172 2.828 1.724 1.172 2.828 1.172 2.106-0.449 2.828-1.172 1.172-1.724 1.172-2.828zM18 12c0 0.553-0.223 1.051-0.586 1.414s-0.861 0.586-1.414 0.586-1.051-0.223-1.414-0.586-0.586-0.861-0.586-1.414 0.223-1.051 0.586-1.414 0.861-0.586 1.414-0.586 1.051 0.223 1.414 0.586 0.586 0.861 0.586 1.414z"></path></symbol>
|
||||||
|
|
||||||
|
<symbol id="icon-x-circle" viewBox="0 0 24 24"><path d="M23 12c0-3.037-1.232-5.789-3.222-7.778s-4.741-3.222-7.778-3.222-5.789 1.232-7.778 3.222-3.222 4.741-3.222 7.778 1.232 5.789 3.222 7.778 4.741 3.222 7.778 3.222 5.789-1.232 7.778-3.222 3.222-4.741 3.222-7.778zM21 12c0 2.486-1.006 4.734-2.636 6.364s-3.878 2.636-6.364 2.636-4.734-1.006-6.364-2.636-2.636-3.878-2.636-6.364 1.006-4.734 2.636-6.364 3.878-2.636 6.364-2.636 4.734 1.006 6.364 2.636 2.636 3.878 2.636 6.364zM8.293 9.707l2.293 2.293-2.293 2.293c-0.391 0.391-0.391 1.024 0 1.414s1.024 0.391 1.414 0l2.293-2.293 2.293 2.293c0.391 0.391 1.024 0.391 1.414 0s0.391-1.024 0-1.414l-2.293-2.293 2.293-2.293c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-2.293 2.293-2.293-2.293c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414z"></path></symbol>
|
||||||
|
|
||||||
|
<symbol id="icon-svg-search" viewBox="0 0 24 24">
|
||||||
|
<title>Search</title>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search">
|
||||||
|
<circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||||
|
</svg>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<symbol id="icon-svg-doc" viewBox="0 0 24 24">
|
||||||
|
<title>Document</title>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file">
|
||||||
|
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
</symbol>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<script src="{{ breadcrumbs }}/js/highlight.min.js?v={{ aiken_version }}"></script>
|
||||||
|
<script src="{{ breadcrumbs }}/js/highlightjs-aiken.js?v={{ aiken_version }}"></script>
|
||||||
|
<script>
|
||||||
|
document.querySelectorAll("pre code").forEach((elem) => {
|
||||||
|
if (elem.className === "") {
|
||||||
|
elem.classList.add("aiken");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
hljs.highlightAll();
|
||||||
|
</script>
|
||||||
|
<script src="{{ breadcrumbs }}/js/lunr.min.js?v={{ aiken_version }}"></script>
|
||||||
|
<script src="{{ breadcrumbs }}/js/index.js?v={{ timestamp }}"></script>
|
||||||
|
<!-- Load the search index using JSONP to avoid CORS issues -->
|
||||||
|
<script src="{{ breadcrumbs }}/search-data.js?v={{ timestamp }}"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1 @@
|
||||||
|
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#abb2bf;background:#282c34}.hljs-comment,.hljs-quote{color:#5c6370;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#c678dd}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e06c75}.hljs-literal{color:#56b6c2}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#98c379}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#d19a66}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#61aeee}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#e6c07b}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}
|
|
@ -0,0 +1 @@
|
||||||
|
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#383a42;background:#fafafa}.hljs-comment,.hljs-quote{color:#a0a1a7;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#a626a4}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e45649}.hljs-literal{color:#0184bb}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#50a14f}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#986801}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#4078f2}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#c18401}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}
|
|
@ -0,0 +1,992 @@
|
||||||
|
@import url("https://fonts.googleapis.com/css2?family=Nunito+Sans&family=Ubuntu+Mono&display=swap");
|
||||||
|
|
||||||
|
:root {
|
||||||
|
/* Sizes */
|
||||||
|
--search-width: 680px;
|
||||||
|
--header-height: 60px;
|
||||||
|
--hash-offset: calc(var(--header-height) * 1.67);
|
||||||
|
--sidebar-width: 240px;
|
||||||
|
--gap: 24px;
|
||||||
|
--small-gap: calc(var(--gap) / 2);
|
||||||
|
--tiny-gap: calc(var(--small-gap) / 2);
|
||||||
|
--large-gap: calc(var(--gap) * 2);
|
||||||
|
--sidebar-toggle-size: 33px;
|
||||||
|
--search-height: 4rem;
|
||||||
|
|
||||||
|
/* Colors */
|
||||||
|
--color-text: #4c4f69;
|
||||||
|
--color-text-accent: #e6e9ef;
|
||||||
|
--color-inline-code: #ea76cb;
|
||||||
|
--color-link: #dc8a78;
|
||||||
|
--color-link-accent: #dd7878;
|
||||||
|
--color-background: #eff1f5;
|
||||||
|
--color-background-sidebar: #e6e9ef;
|
||||||
|
--color-background-accent: #8839ef;
|
||||||
|
--color-border-accent: #ea76cb;
|
||||||
|
--color-table-header-background: #bcc0cc;
|
||||||
|
--color-table-header-text: #4c4f69;
|
||||||
|
--color-table-background: #e6e9ef;
|
||||||
|
--color-table-border: #ea76cb;
|
||||||
|
--color-code-background: #dce0e8;
|
||||||
|
|
||||||
|
/* etc */
|
||||||
|
--nav-shadow: 0 0 6px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
--shadow:
|
||||||
|
0 0 0 1px rgba(50, 50, 93, 0.075),
|
||||||
|
0 0 1px #e9ecef,
|
||||||
|
0 2px 4px -2px rgba(138, 141, 151, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body,
|
||||||
|
html {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-family: "Nunito Sans", sans-serif;
|
||||||
|
font-size: 17px;
|
||||||
|
line-height: 1.4;
|
||||||
|
position: relative;
|
||||||
|
min-height: 100vh;
|
||||||
|
word-break: break-word;
|
||||||
|
background-color: var(--color-background);
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
/* This is necessary so hash targets appear below the fixed header */
|
||||||
|
scroll-padding-top: var(--hash-offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
a:visited {
|
||||||
|
color: var(--color-link);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
select {
|
||||||
|
background: transparent;
|
||||||
|
border: 0 none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 100%;
|
||||||
|
line-height: 1.15;
|
||||||
|
margin: 0;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button::-moz-focus-inner {
|
||||||
|
border-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:-moz-focusring {
|
||||||
|
outline: 1px dotted ButtonText;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
line-height: 1;
|
||||||
|
margin: 0;
|
||||||
|
overflow: visible;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:active,
|
||||||
|
select:active {
|
||||||
|
outline: 0 none;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: var(--small-gap) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rendered-markdown h1,
|
||||||
|
.rendered-markdown h2,
|
||||||
|
.rendered-markdown h3,
|
||||||
|
.rendered-markdown h4,
|
||||||
|
.rendered-markdown h5 {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code */
|
||||||
|
|
||||||
|
pre,
|
||||||
|
code {
|
||||||
|
font-family: "Ubuntu Mono", monospace;
|
||||||
|
line-height: 1.2;
|
||||||
|
background-color: var(--color-code-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin: var(--gap) 0;
|
||||||
|
border-radius: 1px;
|
||||||
|
overflow: auto;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
pre > code,
|
||||||
|
code.hljs {
|
||||||
|
padding: var(--small-gap) var(--gap);
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
td code,
|
||||||
|
p code {
|
||||||
|
margin: 0 2px;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 0.2em;
|
||||||
|
color: var(--color-inline-code);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Page layout */
|
||||||
|
|
||||||
|
.page {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin-left: var(--sidebar-width);
|
||||||
|
padding: calc(var(--header-height) + var(--gap)) var(--gap) 0 var(--gap);
|
||||||
|
width: calc(100% - var(--sidebar-width));
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Page header */
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
box-shadow: var(--nav-shadow);
|
||||||
|
height: var(--header-height);
|
||||||
|
color: var(--color-text-accent);
|
||||||
|
background-color: var(--color-background-accent);
|
||||||
|
display: flex;
|
||||||
|
padding: var(--small-gap) var(--gap);
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header h2 {
|
||||||
|
align-items: baseline;
|
||||||
|
display: flex;
|
||||||
|
margin: 0;
|
||||||
|
width: var(--sidebar-width);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header a,
|
||||||
|
.page-header a:visited {
|
||||||
|
color: var(--color-text-accent);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-toggle {
|
||||||
|
display: none;
|
||||||
|
font-size: var(--sidebar-toggle-size);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-nav-button {
|
||||||
|
display: none;
|
||||||
|
font-size: var(--sidebar-toggle-size);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header .sidebar-toggle {
|
||||||
|
color: var(--color-background);
|
||||||
|
margin: 0 var(--small-gap) 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header .search-nav-button {
|
||||||
|
color: var(--color-background);
|
||||||
|
margin: 0 var(--small-gap) 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Version selector */
|
||||||
|
|
||||||
|
#project-version {
|
||||||
|
--half-small-gap: calc(var(--small-gap) / 2);
|
||||||
|
--icon-size: 0.75em;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-left: var(--half-small-gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
#project-version > span {
|
||||||
|
padding-left: var(--half-small-gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
#project-version form {
|
||||||
|
align-items: center;
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
#project-version select {
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
padding: 0.6rem calc(1.3 * var(--icon-size)) 0.6rem var(--half-small-gap);
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#project-version option {
|
||||||
|
background-color: var(--code-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
#project-version .icon {
|
||||||
|
font-size: var(--icon-size);
|
||||||
|
margin-left: calc(-1.65 * var(--icon-size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Module doc */
|
||||||
|
|
||||||
|
.module-name > a,
|
||||||
|
.module-member-kind > a {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-name > a:hover,
|
||||||
|
.module-member-kind > a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-name {
|
||||||
|
color: var(--color-text);
|
||||||
|
margin: 0 0 var(--gap);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sidebar */
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
background-color: var(--color-background-sidebar);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
max-height: calc(100vh - var(--header-height));
|
||||||
|
overflow-y: auto;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
padding-top: var(--gap);
|
||||||
|
padding-bottom: var(--gap);
|
||||||
|
padding-left: var(--gap);
|
||||||
|
position: fixed;
|
||||||
|
top: var(--header-height);
|
||||||
|
transition: transform 0.5s ease;
|
||||||
|
width: var(--sidebar-width);
|
||||||
|
z-index: 100;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar h2 {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--color-link-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar h3.modules-prefix {
|
||||||
|
color: var(--color-link);
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: var(--small-gap) 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar h3.modules-prefix + ul {
|
||||||
|
margin-left: var(--tiny-gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar li {
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar ul li a > strong {
|
||||||
|
font-weight: 900;
|
||||||
|
color: var(--color-link);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar ul li a > strong::before {
|
||||||
|
font-size: 0.75em;
|
||||||
|
content: 'ᐅ ';
|
||||||
|
padding-right: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar .sidebar-toggle {
|
||||||
|
color: var(--color-link);
|
||||||
|
font-size: calc(0.8 * var(--sidebar-toggle-size));
|
||||||
|
}
|
||||||
|
|
||||||
|
body.drawer-closed .label-open,
|
||||||
|
body.drawer-open .label-closed {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-controls {
|
||||||
|
display: flex;
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-controls svg.icon {
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-controls .control {
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-controls .control:not(:first-child) {
|
||||||
|
margin-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
font-size: 0.96rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-0 .label:not(.label-0),
|
||||||
|
.toggle-1 .label:not(.label-1) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label .icon + .icon {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Module members (types, functions) */
|
||||||
|
|
||||||
|
.module-members {
|
||||||
|
margin-top: var(--large-gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-member-kind {
|
||||||
|
font-size: 2rem;
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.member {
|
||||||
|
margin: var(--large-gap) 0;
|
||||||
|
padding-bottom: var(--gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-name {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-left: 4px solid var(--color-border-accent);
|
||||||
|
padding: var(--small-gap) var(--gap);
|
||||||
|
color: var(--color-text-accent);
|
||||||
|
background-color: var(--color-background-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-name h2 {
|
||||||
|
display: flex;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-name h2 a {
|
||||||
|
color: var(--color-text-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-source {
|
||||||
|
align-self: baseline;
|
||||||
|
flex-shrink: 0;
|
||||||
|
line-height: calc(1.4 * 1.5rem);
|
||||||
|
margin: 0 0 0 var(--small-gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom type constructors */
|
||||||
|
|
||||||
|
.constructor-list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.constructor-row {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.constructor-item {
|
||||||
|
margin-bottom: var(--small-gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
.constructor-argument-item {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.constructor-argument-label {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.constructor-argument-doc {
|
||||||
|
margin-left: var(--gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
.constructor-argument-list {
|
||||||
|
margin-bottom: var(--small-gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
.constructor-item-docs {
|
||||||
|
margin-left: var(--large-gap);
|
||||||
|
margin-bottom: var(--gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
.constructor-item .icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
margin: 0 0.88rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.constructor-name {
|
||||||
|
box-shadow: unset;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.constructor-name > code {
|
||||||
|
padding: var(--small-gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tables */
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-spacing: 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td,
|
||||||
|
table th {
|
||||||
|
padding: 6px 13px;
|
||||||
|
border: 1px solid var(--color-table-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
table th {
|
||||||
|
background-color: var(--color-table-header-background);
|
||||||
|
color: var(--color-table-header-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr:nth-child(2n) {
|
||||||
|
background-color: var(--color-table-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Icons */
|
||||||
|
|
||||||
|
.svg-lib {
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: inline-block;
|
||||||
|
fill: currentColor;
|
||||||
|
height: 1em;
|
||||||
|
stroke: currentColor;
|
||||||
|
stroke-width: 0;
|
||||||
|
width: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pre-Wrap Option */
|
||||||
|
|
||||||
|
body.prewrap-on code,
|
||||||
|
body.prewrap-on pre {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark Theme Option */
|
||||||
|
|
||||||
|
body.theme-dark {
|
||||||
|
/* Colors */
|
||||||
|
--color-text: #cdd6f4;
|
||||||
|
--color-text-accent: #11111b;
|
||||||
|
--color-inline-code: #f5c2e7;
|
||||||
|
--color-link: #f5e0dc;
|
||||||
|
--color-link-accent: #f2cdcd;
|
||||||
|
--color-background: #1e1e2e;
|
||||||
|
--color-background-sidebar: #313244;
|
||||||
|
--color-background-accent: #cba6f7;
|
||||||
|
--color-border-accent: #f5c2e7;
|
||||||
|
--color-table-header-background: #11111b;
|
||||||
|
--color-table-header-text: #cdd6f4;
|
||||||
|
--color-table-background: #181825;
|
||||||
|
--color-table-border: #6c7086;
|
||||||
|
--color-code-background: #11111b;
|
||||||
|
|
||||||
|
/* etc */
|
||||||
|
--nav-shadow: 0 0 5px 5px rgba(0, 0, 0, 0.1);
|
||||||
|
--shadow:
|
||||||
|
0 0 0 1px rgba(50, 50, 93, 0.075),
|
||||||
|
0 0 1px var(--fg-shade-3),
|
||||||
|
0 2px 4px -2px rgba(138, 141, 151, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Medium and larger displays */
|
||||||
|
@media (min-width: 680px) {
|
||||||
|
#prewrap-toggle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Small displays */
|
||||||
|
@media (max-width: 920px) {
|
||||||
|
.page-header {
|
||||||
|
padding-left: var(--small-gap);
|
||||||
|
padding-right: var(--small-gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header h2 {
|
||||||
|
width: calc(
|
||||||
|
100% - var(--sidebar-toggle-size) - var(--small-gap) -
|
||||||
|
var(--sidebar-toggle-size) - var(--small-gap)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
width: 100%;
|
||||||
|
max-width: unset;
|
||||||
|
margin-left: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
box-shadow: var(--nav-shadow);
|
||||||
|
height: 100vh;
|
||||||
|
max-height: unset;
|
||||||
|
top: 0;
|
||||||
|
transform: translate(calc(-10px - var(--sidebar-width)));
|
||||||
|
z-index: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.drawer-open .sidebar {
|
||||||
|
transform: translate(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-toggle {
|
||||||
|
display: block;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-nav-button {
|
||||||
|
display: block;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar .sidebar-toggle {
|
||||||
|
height: var(--sidebar-toggle-size);
|
||||||
|
position: absolute;
|
||||||
|
right: var(--small-gap);
|
||||||
|
top: var(--small-gap);
|
||||||
|
width: var(--sidebar-toggle-size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search */
|
||||||
|
|
||||||
|
.search {
|
||||||
|
display: none;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
flex-grow: 1;
|
||||||
|
height: var(--search-height);
|
||||||
|
padding: 0.5rem;
|
||||||
|
transition: padding linear 200ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) {
|
||||||
|
.search {
|
||||||
|
margin-left: var(--small-gap);
|
||||||
|
display: block;
|
||||||
|
position: relative !important;
|
||||||
|
width: auto !important;
|
||||||
|
height: 100% !important;
|
||||||
|
padding: 0;
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-wrap {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
height: 3rem;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08);
|
||||||
|
transition: height linear 200ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) {
|
||||||
|
.search-input-wrap {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
max-width: calc(var(--search-width) - var(--gap) - var(--gap));
|
||||||
|
height: 100% !important;
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
transition: width ease 400ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
font-size: 16px;
|
||||||
|
background-color: transparent;
|
||||||
|
color: var(--color-text);
|
||||||
|
border-top: 0;
|
||||||
|
border-right: 0;
|
||||||
|
border-bottom: 0;
|
||||||
|
border-left: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) {
|
||||||
|
.search-input {
|
||||||
|
padding: 1rem;
|
||||||
|
font-size: 14px;
|
||||||
|
background-color: var(--color-background);
|
||||||
|
transition: padding-left linear 200ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-label {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
padding-right: 1rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) {
|
||||||
|
.search-label {
|
||||||
|
padding-right: 0.6rem;
|
||||||
|
transition: padding-left linear 200ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-label .search-icon {
|
||||||
|
width: 1.2rem;
|
||||||
|
height: 1.2rem;
|
||||||
|
align-self: center;
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-results {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
display: none;
|
||||||
|
width: 100%;
|
||||||
|
max-height: calc(100% - var(--search-height));
|
||||||
|
overflow-y: auto;
|
||||||
|
color: var(--color-text);
|
||||||
|
background-color: var(--color-background);
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) {
|
||||||
|
.search-results {
|
||||||
|
top: 100%;
|
||||||
|
width: calc(var(--search-width) - var(--gap) - var(--gap));
|
||||||
|
max-height: calc(100vh - 200%) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-results-list {
|
||||||
|
padding-left: 0;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
list-style: none;
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 31.25rem) {
|
||||||
|
.search-results-list {
|
||||||
|
font-size: 16px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) {
|
||||||
|
.search-results-list {
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) and (min-width: 31.25rem) {
|
||||||
|
.search-results-list {
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-results-list-item {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result {
|
||||||
|
display: block;
|
||||||
|
padding-top: 0.25rem;
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
padding-bottom: 0.25rem;
|
||||||
|
padding-left: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result:hover,
|
||||||
|
.search-result.active {
|
||||||
|
background-color: var(--code-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-title {
|
||||||
|
display: block;
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 31.25rem) {
|
||||||
|
.search-result-title {
|
||||||
|
display: inline-block;
|
||||||
|
width: 40%;
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-doc {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-doc.search-result-doc-parent {
|
||||||
|
opacity: 0.5;
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 31.25rem) {
|
||||||
|
.search-result-doc.search-result-doc-parent {
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) {
|
||||||
|
.search-result-doc.search-result-doc-parent {
|
||||||
|
font-size: 11px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) and (min-width: 31.25rem) {
|
||||||
|
.search-result-doc.search-result-doc-parent {
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-doc .search-result-icon {
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
color: var(--color-link-accent);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-doc .search-result-doc-title {
|
||||||
|
overflow: auto;
|
||||||
|
color: var(--color-link-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-section {
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
word-wrap: break-word;
|
||||||
|
color: var(--color-link-accent)
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-rel-url {
|
||||||
|
display: block;
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
overflow: hidden;
|
||||||
|
color: var(--color-text);
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 9px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 31.25rem) {
|
||||||
|
.search-result-rel-url {
|
||||||
|
font-size: 10px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-previews {
|
||||||
|
display: block;
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
padding-left: 1rem;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
color: var(--color-text);
|
||||||
|
word-wrap: break-word;
|
||||||
|
border-left: 1px solid;
|
||||||
|
border-left-color: #eeebee;
|
||||||
|
font-size: 11px !important;
|
||||||
|
/* TODO: fix it by not adding at the parent? */
|
||||||
|
white-space: initial !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 31.25rem) {
|
||||||
|
.search-result-previews {
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 31.25rem) {
|
||||||
|
.search-result-previews {
|
||||||
|
display: inline-block;
|
||||||
|
width: 60%;
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
margin-left: 0;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-preview + .search-result-preview {
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-highlight {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-no-result {
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
padding-left: 0.75rem;
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 31.25rem) {
|
||||||
|
.search-no-result {
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button {
|
||||||
|
position: fixed;
|
||||||
|
right: 1rem;
|
||||||
|
bottom: 1rem;
|
||||||
|
display: flex;
|
||||||
|
width: 3.5rem;
|
||||||
|
height: 3.5rem;
|
||||||
|
background-color: var(--color-background);
|
||||||
|
border: 1px solid rgba(114, 83, 237, 0.3);
|
||||||
|
border-radius: 1.75rem;
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08);
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 101;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity ease 400ms, width 0s 400ms, height 0s 400ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-active .search {
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-active .search-input-wrap {
|
||||||
|
height: var(--search-height);
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) {
|
||||||
|
.search-active .search-input-wrap {
|
||||||
|
width: calc(var(--search-width) - var(--gap) - var(--gap));
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-active .search-input {
|
||||||
|
background-color: var(--color-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) {
|
||||||
|
.search-active .search-label {
|
||||||
|
padding-left: 0.6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-active .search-results {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-active .search-overlay {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity ease 400ms, width 0s, height 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) {
|
||||||
|
.search-active .main {
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-active .main-header {
|
||||||
|
padding-top: var(--search-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 919px) {
|
||||||
|
.search-active .main-header {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 95 KiB |
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,115 @@
|
||||||
|
hljs.registerLanguage("aiken", function (hljs) {
|
||||||
|
const KEYWORDS =
|
||||||
|
"as assert when is const fn if let use opaque pub assert check todo type";
|
||||||
|
const STRING = {
|
||||||
|
className: "string",
|
||||||
|
variants: [{ begin: /"/, end: /"/ }],
|
||||||
|
contains: [hljs.BACKSLASH_ESCAPE],
|
||||||
|
relevance: 0,
|
||||||
|
};
|
||||||
|
const NAME = {
|
||||||
|
className: "variable",
|
||||||
|
begin: "\\b[a-z][a-z0-9_]*\\b",
|
||||||
|
relevance: 0,
|
||||||
|
};
|
||||||
|
const DISCARD_NAME = {
|
||||||
|
className: "comment",
|
||||||
|
begin: "\\b_[a-z][a-z0-9_]*\\b",
|
||||||
|
relevance: 0,
|
||||||
|
};
|
||||||
|
const NUMBER = {
|
||||||
|
className: "number",
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
// binary
|
||||||
|
begin: "\\b0[bB](?:_?[01]+)+",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// octal
|
||||||
|
begin: "\\b0[oO](?:_?[0-7]+)+",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// hex
|
||||||
|
begin: "\\b0[xX](?:_?[0-9a-fA-F]+)+",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// dec, float
|
||||||
|
begin: "\\b\\d(?:_?\\d+)*(?:\\.(?:\\d(?:_?\\d+)*)*)?",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
relevance: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: "Aiken",
|
||||||
|
aliases: ["aiken"],
|
||||||
|
contains: [
|
||||||
|
hljs.C_LINE_COMMENT_MODE,
|
||||||
|
STRING,
|
||||||
|
{
|
||||||
|
// bit string
|
||||||
|
begin: "<<",
|
||||||
|
end: ">>",
|
||||||
|
contains: [
|
||||||
|
{
|
||||||
|
className: "keyword",
|
||||||
|
beginKeywords:
|
||||||
|
"binary bytes int float bit_string bits utf8 utf16 utf32 " +
|
||||||
|
"utf8_codepoint utf16_codepoint utf32_codepoint signed unsigned " +
|
||||||
|
"big little native unit size",
|
||||||
|
},
|
||||||
|
KEYWORDS,
|
||||||
|
STRING,
|
||||||
|
NAME,
|
||||||
|
DISCARD_NAME,
|
||||||
|
NUMBER,
|
||||||
|
],
|
||||||
|
relevance: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: "function",
|
||||||
|
beginKeywords: "fn",
|
||||||
|
end: "\\(",
|
||||||
|
excludeEnd: true,
|
||||||
|
contains: [
|
||||||
|
{
|
||||||
|
className: "title",
|
||||||
|
begin: "[a-z][a-z0-9_]*\\w*",
|
||||||
|
relevance: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: "keyword",
|
||||||
|
beginKeywords: "use",
|
||||||
|
end: "\n",
|
||||||
|
excludeEnd: true,
|
||||||
|
contains: [
|
||||||
|
{
|
||||||
|
className: "title",
|
||||||
|
begin: "[a-z][a-z0-9_/]*\\w*",
|
||||||
|
relevance: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: "keyword",
|
||||||
|
beginKeywords: KEYWORDS,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Type names and constructors
|
||||||
|
className: "title",
|
||||||
|
begin: "\\b[A-Z][A-Za-z0-9]*\\b",
|
||||||
|
relevance: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: "operator",
|
||||||
|
begin: "[+\\-*/%!=<>&|.]+",
|
||||||
|
relevance: 0,
|
||||||
|
},
|
||||||
|
NAME,
|
||||||
|
DISCARD_NAME,
|
||||||
|
NUMBER,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
});
|
|
@ -0,0 +1,609 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
window.Aiken = (function () {
|
||||||
|
/* Global Object */
|
||||||
|
const self = {};
|
||||||
|
|
||||||
|
/* Public Properties */
|
||||||
|
|
||||||
|
self.hashOffset = undefined;
|
||||||
|
|
||||||
|
/* Public Methods */
|
||||||
|
|
||||||
|
self.getProperty = function (property) {
|
||||||
|
let value;
|
||||||
|
try {
|
||||||
|
value = localStorage.getItem(`Aiken.${property}`);
|
||||||
|
} catch (_error) {}
|
||||||
|
if (-1 < [null, undefined].indexOf(value)) {
|
||||||
|
return aikenConfig[property].values[0].value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.icons = function () {
|
||||||
|
return Array.from(arguments).reduce(
|
||||||
|
(acc, name) =>
|
||||||
|
`${acc}
|
||||||
|
<svg class="icon icon-${name}"><use xlink:href="#icon-${name}"></use></svg>`,
|
||||||
|
""
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.scrollToHash = function () {
|
||||||
|
const locationHash = arguments[0] || window.location.hash;
|
||||||
|
const query = locationHash ? locationHash : "body";
|
||||||
|
const hashTop = document.querySelector(query).offsetTop;
|
||||||
|
window.scrollTo(0, hashTop - self.hashOffset);
|
||||||
|
return locationHash;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.toggleSidebar = function () {
|
||||||
|
const previousState = bodyClasses.contains("drawer-open")
|
||||||
|
? "open"
|
||||||
|
: "closed";
|
||||||
|
|
||||||
|
let state;
|
||||||
|
if (0 < arguments.length) {
|
||||||
|
state = false === arguments[0] ? "closed" : "open";
|
||||||
|
} else {
|
||||||
|
state = "open" === previousState ? "closed" : "open";
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyClasses.remove(`drawer-${previousState}`);
|
||||||
|
bodyClasses.add(`drawer-${state}`);
|
||||||
|
|
||||||
|
if ("open" === state) {
|
||||||
|
document.addEventListener("click", closeSidebar, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Private Properties */
|
||||||
|
|
||||||
|
const html = document.documentElement;
|
||||||
|
const body = document.body;
|
||||||
|
const bodyClasses = body.classList;
|
||||||
|
const sidebar = document.querySelector(".sidebar");
|
||||||
|
const sidebarToggles = document.querySelectorAll(".sidebar-toggle");
|
||||||
|
const displayControls = document.createElement("div");
|
||||||
|
|
||||||
|
displayControls.classList.add("display-controls");
|
||||||
|
sidebar.appendChild(displayControls);
|
||||||
|
|
||||||
|
/* Private Methods */
|
||||||
|
|
||||||
|
const initProperty = function (property) {
|
||||||
|
const config = aikenConfig[property];
|
||||||
|
|
||||||
|
displayControls.insertAdjacentHTML(
|
||||||
|
"beforeend",
|
||||||
|
config.values.reduce(
|
||||||
|
(acc, item, index) => {
|
||||||
|
const tooltip = item.label
|
||||||
|
? `alt="${item.label}" title="${item.label}"`
|
||||||
|
: "";
|
||||||
|
let inner;
|
||||||
|
if (item.icons) {
|
||||||
|
inner = self.icons(...item.icons);
|
||||||
|
} else if (item.label) {
|
||||||
|
inner = item.label;
|
||||||
|
} else {
|
||||||
|
inner = "";
|
||||||
|
}
|
||||||
|
return `
|
||||||
|
${acc}
|
||||||
|
<span class="label label-${index}" ${tooltip}>
|
||||||
|
${inner}
|
||||||
|
</span>
|
||||||
|
`;
|
||||||
|
},
|
||||||
|
`<button
|
||||||
|
id="${property}-toggle"
|
||||||
|
class="control control-${property} toggle toggle-0">
|
||||||
|
`
|
||||||
|
) +
|
||||||
|
`
|
||||||
|
</button>
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
setProperty(null, property, function () {
|
||||||
|
return self.getProperty(property);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const setProperty = function (_event, property) {
|
||||||
|
const previousValue = self.getProperty(property);
|
||||||
|
|
||||||
|
const update =
|
||||||
|
2 < arguments.length ? arguments[2] : aikenConfig[property].update;
|
||||||
|
const value = update();
|
||||||
|
|
||||||
|
try {
|
||||||
|
localStorage.setItem("Aiken." + property, value);
|
||||||
|
} catch (_error) {}
|
||||||
|
|
||||||
|
bodyClasses.remove(`${property}-${previousValue}`);
|
||||||
|
bodyClasses.add(`${property}-${value}`);
|
||||||
|
|
||||||
|
const isDefault = value === aikenConfig[property].values[0].value;
|
||||||
|
const toggleClasses = document.querySelector(
|
||||||
|
`#${property}-toggle`
|
||||||
|
).classList;
|
||||||
|
toggleClasses.remove(`toggle-${isDefault ? 1 : 0}`);
|
||||||
|
toggleClasses.add(`toggle-${isDefault ? 0 : 1}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
aikenConfig[property].callback(value);
|
||||||
|
} catch (_error) {}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const setHashOffset = function () {
|
||||||
|
const el = document.createElement("div");
|
||||||
|
el.style.cssText = `
|
||||||
|
height: var(--hash-offset);
|
||||||
|
pointer-events: none;
|
||||||
|
position: absolute;
|
||||||
|
visibility: hidden;
|
||||||
|
width: 0;
|
||||||
|
`;
|
||||||
|
body.appendChild(el);
|
||||||
|
self.hashOffset = parseInt(
|
||||||
|
getComputedStyle(el).getPropertyValue("height") || "0"
|
||||||
|
);
|
||||||
|
body.removeChild(el);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeSidebar = function (event) {
|
||||||
|
if (!event.target.closest(".sidebar-toggle")) {
|
||||||
|
document.removeEventListener("click", closeSidebar, false);
|
||||||
|
self.toggleSidebar(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addEvent = function (el, type, handler) {
|
||||||
|
if (el.attachEvent) el.attachEvent("on" + type, handler);
|
||||||
|
else el.addEventListener(type, handler);
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchLoaded = function (index, docs) {
|
||||||
|
const preview_words_after = 10;
|
||||||
|
const preview_words_before = 5;
|
||||||
|
const previews = 3;
|
||||||
|
|
||||||
|
const searchInput = document.getElementById("search-input");
|
||||||
|
const searchNavButton = document.getElementById("search-nav-button");
|
||||||
|
const searchResults = document.getElementById("search-results");
|
||||||
|
let currentInput;
|
||||||
|
let currentSearchIndex = 0;
|
||||||
|
|
||||||
|
function showSearch() {
|
||||||
|
document.documentElement.classList.add("search-active");
|
||||||
|
}
|
||||||
|
|
||||||
|
searchNavButton.addEventListener("click", function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
showSearch();
|
||||||
|
setTimeout(function () {
|
||||||
|
searchInput.focus();
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
function hideSearch() {
|
||||||
|
document.documentElement.classList.remove("search-active");
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
currentSearchIndex++;
|
||||||
|
|
||||||
|
const input = searchInput.value;
|
||||||
|
showSearch();
|
||||||
|
if (input === currentInput) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentInput = input;
|
||||||
|
searchResults.innerHTML = "";
|
||||||
|
if (input === "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let results = index.query(function (query) {
|
||||||
|
const tokens = lunr.tokenizer(input);
|
||||||
|
query.term(tokens, {
|
||||||
|
boost: 10,
|
||||||
|
});
|
||||||
|
query.term(tokens, {
|
||||||
|
wildcard: lunr.Query.wildcard.TRAILING,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (results.length == 0 && input.length > 2) {
|
||||||
|
const tokens = lunr.tokenizer(input).filter(function (token, i) {
|
||||||
|
return token.str.length < 20;
|
||||||
|
});
|
||||||
|
if (tokens.length > 0) {
|
||||||
|
results = index.query(function (query) {
|
||||||
|
query.term(tokens, {
|
||||||
|
editDistance: Math.round(Math.sqrt(input.length / 2 - 1)),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.length == 0) {
|
||||||
|
const noResultsDiv = document.createElement("div");
|
||||||
|
noResultsDiv.classList.add("search-no-result");
|
||||||
|
noResultsDiv.innerText = "No results found";
|
||||||
|
searchResults.appendChild(noResultsDiv);
|
||||||
|
} else {
|
||||||
|
const resultsList = document.createElement("ul");
|
||||||
|
resultsList.classList.add("search-results-list");
|
||||||
|
searchResults.appendChild(resultsList);
|
||||||
|
|
||||||
|
addResults(resultsList, results, 0, 10, 100, currentSearchIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addResults(
|
||||||
|
resultsList,
|
||||||
|
results,
|
||||||
|
start,
|
||||||
|
batchSize,
|
||||||
|
batchMillis,
|
||||||
|
searchIndex
|
||||||
|
) {
|
||||||
|
if (searchIndex != currentSearchIndex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let i = start; i < start + batchSize; i++) {
|
||||||
|
if (i == results.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addResult(resultsList, results[i]);
|
||||||
|
}
|
||||||
|
setTimeout(function () {
|
||||||
|
addResults(
|
||||||
|
resultsList,
|
||||||
|
results,
|
||||||
|
start + batchSize,
|
||||||
|
batchSize,
|
||||||
|
batchMillis,
|
||||||
|
searchIndex
|
||||||
|
);
|
||||||
|
}, batchMillis);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addResult(resultsList, result) {
|
||||||
|
const doc = docs[result.ref];
|
||||||
|
const resultsListItem = document.createElement("li");
|
||||||
|
resultsListItem.classList.add("search-results-list-item");
|
||||||
|
resultsList.appendChild(resultsListItem);
|
||||||
|
const resultLink = document.createElement("a");
|
||||||
|
resultLink.classList.add("search-result");
|
||||||
|
resultLink.setAttribute("href", `${window.breadcrumbs}/${doc.url}`);
|
||||||
|
resultsListItem.appendChild(resultLink);
|
||||||
|
const resultTitle = document.createElement("div");
|
||||||
|
resultTitle.classList.add("search-result-title");
|
||||||
|
resultLink.appendChild(resultTitle);
|
||||||
|
const resultDoc = document.createElement("div");
|
||||||
|
resultDoc.classList.add("search-result-doc");
|
||||||
|
resultDoc.innerHTML =
|
||||||
|
'<svg viewBox="0 0 24 24" class="search-result-icon"><use xlink:href="#icon-svg-doc"></use></svg>';
|
||||||
|
resultTitle.appendChild(resultDoc);
|
||||||
|
const resultDocTitle = document.createElement("div");
|
||||||
|
resultDocTitle.classList.add("search-result-doc-title");
|
||||||
|
resultDocTitle.innerHTML = doc.doc;
|
||||||
|
resultDoc.appendChild(resultDocTitle);
|
||||||
|
let resultDocOrSection = resultDocTitle;
|
||||||
|
if (doc.doc != doc.title) {
|
||||||
|
resultDoc.classList.add("search-result-doc-parent");
|
||||||
|
const resultSection = document.createElement("div");
|
||||||
|
resultSection.classList.add("search-result-section");
|
||||||
|
resultSection.innerHTML = doc.title;
|
||||||
|
resultTitle.appendChild(resultSection);
|
||||||
|
resultDocOrSection = resultSection;
|
||||||
|
}
|
||||||
|
const metadata = result.matchData.metadata;
|
||||||
|
const titlePositions = [];
|
||||||
|
const contentPositions = [];
|
||||||
|
for (let j in metadata) {
|
||||||
|
const meta = metadata[j];
|
||||||
|
if (meta.title) {
|
||||||
|
const positions = meta.title.position;
|
||||||
|
for (let k in positions) {
|
||||||
|
titlePositions.push(positions[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (meta.content) {
|
||||||
|
const positions = meta.content.position;
|
||||||
|
for (let k in positions) {
|
||||||
|
const position = positions[k];
|
||||||
|
let previewStart = position[0];
|
||||||
|
let previewEnd = position[0] + position[1];
|
||||||
|
let ellipsesBefore = true;
|
||||||
|
let ellipsesAfter = true;
|
||||||
|
for (let k = 0; k < preview_words_before; k++) {
|
||||||
|
const nextSpace = doc.content.lastIndexOf(
|
||||||
|
" ",
|
||||||
|
previewStart - 2
|
||||||
|
);
|
||||||
|
const nextDot = doc.content.lastIndexOf(". ", previewStart - 2);
|
||||||
|
if (nextDot >= 0 && nextDot > nextSpace) {
|
||||||
|
previewStart = nextDot + 1;
|
||||||
|
ellipsesBefore = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nextSpace < 0) {
|
||||||
|
previewStart = 0;
|
||||||
|
ellipsesBefore = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
previewStart = nextSpace + 1;
|
||||||
|
}
|
||||||
|
for (let k = 0; k < preview_words_after; k++) {
|
||||||
|
const nextSpace = doc.content.indexOf(" ", previewEnd + 1);
|
||||||
|
const nextDot = doc.content.indexOf(". ", previewEnd + 1);
|
||||||
|
if (nextDot >= 0 && nextDot < nextSpace) {
|
||||||
|
previewEnd = nextDot;
|
||||||
|
ellipsesAfter = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nextSpace < 0) {
|
||||||
|
previewEnd = doc.content.length;
|
||||||
|
ellipsesAfter = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
previewEnd = nextSpace;
|
||||||
|
}
|
||||||
|
contentPositions.push({
|
||||||
|
highlight: position,
|
||||||
|
previewStart: previewStart,
|
||||||
|
previewEnd: previewEnd,
|
||||||
|
ellipsesBefore: ellipsesBefore,
|
||||||
|
ellipsesAfter: ellipsesAfter,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (titlePositions.length > 0) {
|
||||||
|
titlePositions.sort(function (p1, p2) {
|
||||||
|
return p1[0] - p2[0];
|
||||||
|
});
|
||||||
|
resultDocOrSection.innerHTML = "";
|
||||||
|
addHighlightedText(
|
||||||
|
resultDocOrSection,
|
||||||
|
doc.title,
|
||||||
|
0,
|
||||||
|
doc.title.length,
|
||||||
|
titlePositions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (contentPositions.length > 0) {
|
||||||
|
contentPositions.sort(function (p1, p2) {
|
||||||
|
return p1.highlight[0] - p2.highlight[0];
|
||||||
|
});
|
||||||
|
let contentPosition = contentPositions[0];
|
||||||
|
let previewPosition = {
|
||||||
|
highlight: [contentPosition.highlight],
|
||||||
|
previewStart: contentPosition.previewStart,
|
||||||
|
previewEnd: contentPosition.previewEnd,
|
||||||
|
ellipsesBefore: contentPosition.ellipsesBefore,
|
||||||
|
ellipsesAfter: contentPosition.ellipsesAfter,
|
||||||
|
};
|
||||||
|
const previewPositions = [previewPosition];
|
||||||
|
for (let j = 1; j < contentPositions.length; j++) {
|
||||||
|
contentPosition = contentPositions[j];
|
||||||
|
if (previewPosition.previewEnd < contentPosition.previewStart) {
|
||||||
|
previewPosition = {
|
||||||
|
highlight: [contentPosition.highlight],
|
||||||
|
previewStart: contentPosition.previewStart,
|
||||||
|
previewEnd: contentPosition.previewEnd,
|
||||||
|
ellipsesBefore: contentPosition.ellipsesBefore,
|
||||||
|
ellipsesAfter: contentPosition.ellipsesAfter,
|
||||||
|
};
|
||||||
|
previewPositions.push(previewPosition);
|
||||||
|
} else {
|
||||||
|
previewPosition.highlight.push(contentPosition.highlight);
|
||||||
|
previewPosition.previewEnd = contentPosition.previewEnd;
|
||||||
|
previewPosition.ellipsesAfter = contentPosition.ellipsesAfter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const resultPreviews = document.createElement("div");
|
||||||
|
resultPreviews.classList.add("search-result-previews");
|
||||||
|
resultLink.appendChild(resultPreviews);
|
||||||
|
const content = doc.content;
|
||||||
|
for (
|
||||||
|
let j = 0;
|
||||||
|
j < Math.min(previewPositions.length, previews);
|
||||||
|
j++
|
||||||
|
) {
|
||||||
|
const position = previewPositions[j];
|
||||||
|
const resultPreview = document.createElement("div");
|
||||||
|
resultPreview.classList.add("search-result-preview");
|
||||||
|
resultPreviews.appendChild(resultPreview);
|
||||||
|
if (position.ellipsesBefore) {
|
||||||
|
resultPreview.appendChild(document.createTextNode("... "));
|
||||||
|
}
|
||||||
|
addHighlightedText(
|
||||||
|
resultPreview,
|
||||||
|
content,
|
||||||
|
position.previewStart,
|
||||||
|
position.previewEnd,
|
||||||
|
position.highlight
|
||||||
|
);
|
||||||
|
if (position.ellipsesAfter) {
|
||||||
|
resultPreview.appendChild(document.createTextNode(" ..."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const resultRelUrl = document.createElement("span");
|
||||||
|
resultRelUrl.classList.add("search-result-rel-url");
|
||||||
|
resultRelUrl.innerText = doc.url;
|
||||||
|
resultTitle.appendChild(resultRelUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addHighlightedText(parent, text, start, end, positions) {
|
||||||
|
let index = start;
|
||||||
|
for (let i in positions) {
|
||||||
|
const position = positions[i];
|
||||||
|
const span = document.createElement("span");
|
||||||
|
span.innerHTML = text.substring(index, position[0]);
|
||||||
|
parent.appendChild(span);
|
||||||
|
index = position[0] + position[1];
|
||||||
|
const highlight = document.createElement("span");
|
||||||
|
highlight.classList.add("search-result-highlight");
|
||||||
|
highlight.innerHTML = text.substring(position[0], index);
|
||||||
|
parent.appendChild(highlight);
|
||||||
|
}
|
||||||
|
const span = document.createElement("span");
|
||||||
|
span.innerHTML = text.substring(index, end);
|
||||||
|
parent.appendChild(span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addEvent(searchInput, "focus", function () {
|
||||||
|
setTimeout(update, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
addEvent(searchInput, "keyup", function (e) {
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case 27: // When esc key is pressed, hide the results and clear the field
|
||||||
|
searchInput.value = "";
|
||||||
|
break;
|
||||||
|
case 38: // arrow up
|
||||||
|
case 40: // arrow down
|
||||||
|
case 13: // enter
|
||||||
|
e.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
|
||||||
|
addEvent(searchInput, "keydown", function (e) {
|
||||||
|
let active;
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case 38: // arrow up
|
||||||
|
e.preventDefault();
|
||||||
|
active = document.querySelector(".search-result.active");
|
||||||
|
if (active) {
|
||||||
|
active.classList.remove("active");
|
||||||
|
if (active.parentElement.previousSibling) {
|
||||||
|
const previous =
|
||||||
|
active.parentElement.previousSibling.querySelector(
|
||||||
|
".search-result"
|
||||||
|
);
|
||||||
|
previous.classList.add("active");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case 40: // arrow down
|
||||||
|
e.preventDefault();
|
||||||
|
active = document.querySelector(".search-result.active");
|
||||||
|
if (active) {
|
||||||
|
if (active.parentElement.nextSibling) {
|
||||||
|
const next =
|
||||||
|
active.parentElement.nextSibling.querySelector(
|
||||||
|
".search-result"
|
||||||
|
);
|
||||||
|
active.classList.remove("active");
|
||||||
|
next.classList.add("active");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const next = document.querySelector(".search-result");
|
||||||
|
if (next) {
|
||||||
|
next.classList.add("active");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case 13: // enter
|
||||||
|
e.preventDefault();
|
||||||
|
active = document.querySelector(".search-result.active");
|
||||||
|
if (active) {
|
||||||
|
active.click();
|
||||||
|
} else {
|
||||||
|
const first = document.querySelector(".search-result");
|
||||||
|
if (first) {
|
||||||
|
first.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addEvent(document, "click", function (e) {
|
||||||
|
if (e.target != searchInput) {
|
||||||
|
hideSearch();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.initSearch = function initSeach(docs) {
|
||||||
|
// enable support for hyphenated search words
|
||||||
|
lunr.tokenizer.separator = /[\s/]+/;
|
||||||
|
|
||||||
|
const index = lunr(function () {
|
||||||
|
this.ref("id");
|
||||||
|
this.field("title", { boost: 200 });
|
||||||
|
this.field("content", { boost: 2 });
|
||||||
|
this.field("url");
|
||||||
|
this.metadataWhitelist = ["position"];
|
||||||
|
|
||||||
|
for (let [i, entry] of docs.entries()) {
|
||||||
|
this.add({
|
||||||
|
id: i,
|
||||||
|
title: entry.title,
|
||||||
|
content: entry.content,
|
||||||
|
url: `${window.breadcrumbs}/${entry.url}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
searchLoaded(index, docs);
|
||||||
|
};
|
||||||
|
|
||||||
|
const init = function () {
|
||||||
|
for (let property in aikenConfig) {
|
||||||
|
initProperty(property);
|
||||||
|
const toggle = document.querySelector(`#${property}-toggle`);
|
||||||
|
toggle.addEventListener("click", function (event) {
|
||||||
|
setProperty(event, property);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sidebarToggles.forEach(function (sidebarToggle) {
|
||||||
|
sidebarToggle.addEventListener("click", function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
self.toggleSidebar();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setHashOffset();
|
||||||
|
window.addEventListener("load", function (_event) {
|
||||||
|
self.scrollToHash();
|
||||||
|
});
|
||||||
|
window.addEventListener("hashchange", function (_event) {
|
||||||
|
self.scrollToHash();
|
||||||
|
});
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelectorAll(
|
||||||
|
`
|
||||||
|
.module-name > a,
|
||||||
|
.member-name a[href^='#']
|
||||||
|
`
|
||||||
|
)
|
||||||
|
.forEach(function (title) {
|
||||||
|
title.innerHTML = title.innerHTML.replace(
|
||||||
|
/([A-Z])|([_/])/g,
|
||||||
|
"$2<wbr>$1"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Initialise */
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
return self;
|
||||||
|
})();
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,165 @@
|
||||||
|
{% extends "_layout.html" %}
|
||||||
|
|
||||||
|
{% block sidebar_content %}
|
||||||
|
{% if !types.is_empty() %}
|
||||||
|
<h2>Types</h2>
|
||||||
|
<ul>
|
||||||
|
{% for type_info in types %}
|
||||||
|
<li><a href="#{{ type_info.name }}">{{ type_info.name }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if !constants.is_empty() %}
|
||||||
|
<h2>Constants</h2>
|
||||||
|
<ul>
|
||||||
|
{% for constant in constants %}
|
||||||
|
<li><a href="#{{ constant.name }}">{{ constant.name }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if !functions.is_empty() %}
|
||||||
|
<h2>Functions</h2>
|
||||||
|
<ul>
|
||||||
|
{% for function in functions %}
|
||||||
|
<li><a href="#{{ function.name }}">{{ function.name }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1 id="module-name" class="module-name">
|
||||||
|
<a href="#module-name">{{ module_name }}</a>
|
||||||
|
</h1>
|
||||||
|
{{ documentation|safe }}
|
||||||
|
|
||||||
|
{% if !types.is_empty() %}
|
||||||
|
<section class="module-members">
|
||||||
|
<h1 id="module-types" class="module-member-kind">
|
||||||
|
<a href="#module-types">Types</a>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{% for type_info in types %}
|
||||||
|
<div class="member">
|
||||||
|
<div class="member-name">
|
||||||
|
<h2 id="{{ type_info.name }}">
|
||||||
|
<a href="#{{ type_info.name }}">
|
||||||
|
{{ type_info.name }}
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
{% if !type_info.source_url.is_empty() %}
|
||||||
|
<!-- TODO: support source linking
|
||||||
|
<a class="member-source" alt="View Source" title="View Source" href="{{ type_info.source_url|safe }}">
|
||||||
|
</>
|
||||||
|
</a>
|
||||||
|
-->
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="custom-type-constructors">
|
||||||
|
<div class="rendered-markdown">{{ type_info.documentation|safe }}</div>
|
||||||
|
<pre><code class="hljs aiken">{{ type_info.definition }}</code></pre>
|
||||||
|
{% if !type_info.constructors.is_empty() %}
|
||||||
|
<h3>
|
||||||
|
Constructors
|
||||||
|
</h3>
|
||||||
|
<ul class="constructor-list">
|
||||||
|
{% for constructor in type_info.constructors %}
|
||||||
|
<li class="constructor-item">
|
||||||
|
<div class="constructor-row">
|
||||||
|
<svg class="icon icon-star"><use xlink:href="#icon-star"></use></svg>
|
||||||
|
<pre class="constructor-name"><code class="hljs aiken">{{ constructor.definition }}</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="constructor-item-docs">
|
||||||
|
{{ constructor.documentation|safe }}
|
||||||
|
|
||||||
|
{% if !constructor.arguments.is_empty() %}
|
||||||
|
<h4>
|
||||||
|
Arguments
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<ul class="constructor-argument-list">
|
||||||
|
{% for argument in constructor.arguments %}
|
||||||
|
<li>
|
||||||
|
<div class="constructor-argument-item">
|
||||||
|
<p class="constructor-argument-label">
|
||||||
|
<i>{{ argument.label }}</i>
|
||||||
|
</p>
|
||||||
|
<div class="constructor-argument-doc">
|
||||||
|
{{ argument.documentation|safe }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if !constants.is_empty() %}
|
||||||
|
<section class="module-members">
|
||||||
|
<h1 id="module-constants" class="module-member-kind">
|
||||||
|
<a href="#module-constants">Constants</a>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{% for constant in constants %}
|
||||||
|
<div class="member">
|
||||||
|
<div class="member-name">
|
||||||
|
<h2 id="{{ constant.name }}">
|
||||||
|
<a href="#{{ constant.name }}">
|
||||||
|
{{ constant.name }}
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
{% if !constant.source_url.is_empty() %}
|
||||||
|
<!-- TODO: support source linking
|
||||||
|
<a class="member-source" alt="View Source" title="View Source" href="{{ constant.source_url|safe }}">
|
||||||
|
</>
|
||||||
|
</a>
|
||||||
|
-->
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<pre><code class="hljs aiken">{{ constant.definition }}</code></pre>
|
||||||
|
<div class="rendered-markdown">{{ constant.documentation|safe }}</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if !functions.is_empty() %}
|
||||||
|
<section class="module-members">
|
||||||
|
<h1 id="module-functions" class="module-member-kind">
|
||||||
|
<a href="#module-functions">Functions</a>
|
||||||
|
</h1>
|
||||||
|
{% for function in functions %}
|
||||||
|
<div class="member">
|
||||||
|
<div class="member-name">
|
||||||
|
<h2 id="{{ function.name }}">
|
||||||
|
<a href="#{{ function.name }}">
|
||||||
|
{{ function.name }}
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
{% if !function.source_url.is_empty() %}
|
||||||
|
<!-- TODO: support source linking
|
||||||
|
<a class="member-source" alt="View Source" title="View Source" href="{{ function.source_url|safe }}">
|
||||||
|
</>
|
||||||
|
</a>
|
||||||
|
-->
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<pre><code class="hljs aiken">{{ function.signature }}</code></pre>
|
||||||
|
<div class="rendered-markdown">{{ function.documentation|safe }}</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{% extends "_layout.html" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{{ title }} - {{ project_name }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{{ content|safe }}
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue