mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
docs flow working with mocked markup to html
This commit is contained in:
parent
28cf11a1d9
commit
f63c276a5f
9 changed files with 178 additions and 135 deletions
|
@ -214,7 +214,7 @@ pub fn build_app<'a>() -> App<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn docs(files: Vec<PathBuf>) {
|
pub fn docs(files: Vec<PathBuf>) {
|
||||||
roc_docs::generate(
|
roc_docs::generate_docs_html(
|
||||||
files,
|
files,
|
||||||
roc_builtins::std::standard_stdlib(),
|
roc_builtins::std::standard_stdlib(),
|
||||||
Path::new("./generated-docs"),
|
Path::new("./generated-docs"),
|
||||||
|
|
|
@ -13,7 +13,6 @@ use super::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::markup_error::{ExpectedTextNode, NestedNodeMissingChild, NestedNodeRequired};
|
use crate::markup_error::{ExpectedTextNode, NestedNodeMissingChild, NestedNodeRequired};
|
||||||
use bumpalo::Bump;
|
|
||||||
use roc_ast::{
|
use roc_ast::{
|
||||||
ast_error::ASTResult,
|
ast_error::ASTResult,
|
||||||
lang::{
|
lang::{
|
||||||
|
@ -306,7 +305,6 @@ fn new_markup_node(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn def2_to_markup<'a, 'b>(
|
pub fn def2_to_markup<'a, 'b>(
|
||||||
arena: &'a Bump,
|
|
||||||
env: &mut Env<'b>,
|
env: &mut Env<'b>,
|
||||||
def2: &Def2,
|
def2: &Def2,
|
||||||
def2_node_id: DefId,
|
def2_node_id: DefId,
|
||||||
|
@ -321,7 +319,6 @@ pub fn def2_to_markup<'a, 'b>(
|
||||||
expr_id,
|
expr_id,
|
||||||
} => {
|
} => {
|
||||||
let expr_mn_id = expr2_to_markup(
|
let expr_mn_id = expr2_to_markup(
|
||||||
arena,
|
|
||||||
env,
|
env,
|
||||||
env.pool.get(*expr_id),
|
env.pool.get(*expr_id),
|
||||||
*expr_id,
|
*expr_id,
|
||||||
|
@ -348,7 +345,6 @@ pub fn def2_to_markup<'a, 'b>(
|
||||||
|
|
||||||
// make Markup Nodes: generate String representation, assign Highlighting Style
|
// make Markup Nodes: generate String representation, assign Highlighting Style
|
||||||
pub fn expr2_to_markup<'a, 'b>(
|
pub fn expr2_to_markup<'a, 'b>(
|
||||||
arena: &'a Bump,
|
|
||||||
env: &mut Env<'b>,
|
env: &mut Env<'b>,
|
||||||
expr2: &Expr2,
|
expr2: &Expr2,
|
||||||
expr2_node_id: ExprId,
|
expr2_node_id: ExprId,
|
||||||
|
@ -380,7 +376,7 @@ pub fn expr2_to_markup<'a, 'b>(
|
||||||
),
|
),
|
||||||
Expr2::Call { expr: expr_id, .. } => {
|
Expr2::Call { expr: expr_id, .. } => {
|
||||||
let expr = env.pool.get(*expr_id);
|
let expr = env.pool.get(*expr_id);
|
||||||
expr2_to_markup(arena, env, expr, *expr_id, mark_node_pool, interns)?
|
expr2_to_markup(env, expr, *expr_id, mark_node_pool, interns)?
|
||||||
}
|
}
|
||||||
Expr2::Var(symbol) => {
|
Expr2::Var(symbol) => {
|
||||||
//TODO make bump_format with arena
|
//TODO make bump_format with arena
|
||||||
|
@ -398,7 +394,6 @@ pub fn expr2_to_markup<'a, 'b>(
|
||||||
let sub_expr2 = env.pool.get(*node_id);
|
let sub_expr2 = env.pool.get(*node_id);
|
||||||
|
|
||||||
children_ids.push(expr2_to_markup(
|
children_ids.push(expr2_to_markup(
|
||||||
arena,
|
|
||||||
env,
|
env,
|
||||||
sub_expr2,
|
sub_expr2,
|
||||||
*node_id,
|
*node_id,
|
||||||
|
@ -460,7 +455,6 @@ pub fn expr2_to_markup<'a, 'b>(
|
||||||
|
|
||||||
let sub_expr2 = env.pool.get(*sub_expr2_node_id);
|
let sub_expr2 = env.pool.get(*sub_expr2_node_id);
|
||||||
children_ids.push(expr2_to_markup(
|
children_ids.push(expr2_to_markup(
|
||||||
arena,
|
|
||||||
env,
|
env,
|
||||||
sub_expr2,
|
sub_expr2,
|
||||||
*sub_expr2_node_id,
|
*sub_expr2_node_id,
|
||||||
|
@ -520,7 +514,6 @@ pub fn expr2_to_markup<'a, 'b>(
|
||||||
expr_var: _,
|
expr_var: _,
|
||||||
} => {
|
} => {
|
||||||
let body_mn_id = expr2_to_markup(
|
let body_mn_id = expr2_to_markup(
|
||||||
arena,
|
|
||||||
env,
|
env,
|
||||||
env.pool.get(*expr_id),
|
env.pool.get(*expr_id),
|
||||||
*expr_id,
|
*expr_id,
|
||||||
|
@ -798,7 +791,6 @@ fn add_header_mn_list(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ast_to_mark_nodes<'a, 'b>(
|
pub fn ast_to_mark_nodes<'a, 'b>(
|
||||||
arena: &'a Bump,
|
|
||||||
env: &mut Env<'b>,
|
env: &mut Env<'b>,
|
||||||
ast: &AST,
|
ast: &AST,
|
||||||
mark_node_pool: &mut SlowPool,
|
mark_node_pool: &mut SlowPool,
|
||||||
|
@ -809,7 +801,7 @@ pub fn ast_to_mark_nodes<'a, 'b>(
|
||||||
for &def_id in ast.def_ids.iter() {
|
for &def_id in ast.def_ids.iter() {
|
||||||
let def2 = env.pool.get(def_id);
|
let def2 = env.pool.get(def_id);
|
||||||
|
|
||||||
let def2_markup_id = def2_to_markup(arena, env, def2, def_id, mark_node_pool, interns)?;
|
let def2_markup_id = def2_to_markup(env, def2, def_id, mark_node_pool, interns)?;
|
||||||
|
|
||||||
set_parent_for_all(def2_markup_id, mark_node_pool);
|
set_parent_for_all(def2_markup_id, mark_node_pool);
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ impl Scope {
|
||||||
self.idents.len()
|
self.idents.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup(&mut self, ident: &Ident, region: Region) -> Result<Symbol, RuntimeError> {
|
pub fn lookup(&self, ident: &Ident, region: Region) -> Result<Symbol, RuntimeError> {
|
||||||
match self.idents.get(ident) {
|
match self.idents.get(ident) {
|
||||||
Some((symbol, _)) => Ok(*symbol),
|
Some((symbol, _)) => Ok(*symbol),
|
||||||
None => Err(RuntimeError::LookupNotInScope(
|
None => Err(RuntimeError::LookupNotInScope(
|
||||||
|
|
|
@ -1,14 +1,4 @@
|
||||||
use crate::html::ToHtml;
|
use crate::html::ToHtml;
|
||||||
use roc_code_markup::{markup::nodes::{MarkupNode}};
|
|
||||||
|
|
||||||
impl<'a> ToHtml<'a> for MarkupNode {
|
|
||||||
fn css_class(&self) -> Option<&'a str> {
|
|
||||||
Some("operator")
|
|
||||||
}
|
|
||||||
fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) {
|
|
||||||
buf.push_str("MarkupNode")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EqualSign;
|
struct EqualSign;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
use crate::html::ToHtml;
|
use crate::html::ToHtml;
|
||||||
use bumpalo::Bump;
|
use roc_ast::{ast_error::ASTResult, lang::{self, core::expr::expr_to_expr2::expr_to_expr2}, mem_pool::pool::Pool};
|
||||||
use roc_ast::{ast_error::ASTResult, lang::{core::expr::expr_to_expr2::expr_to_expr2, env::Env, scope::Scope}, mem_pool::pool::Pool};
|
|
||||||
use roc_code_markup::{markup::nodes::expr2_to_markup, slow_pool::SlowPool};
|
use roc_code_markup::{markup::nodes::expr2_to_markup, slow_pool::SlowPool};
|
||||||
use roc_module::symbol::Interns;
|
use roc_module::symbol::Interns;
|
||||||
use roc_parse::ast::{Expr, StrLiteral};
|
use roc_parse::ast::{Expr, StrLiteral};
|
||||||
use roc_region::all::{Located, Region};
|
use roc_region::all::{Region};
|
||||||
|
use roc_code_markup::{markup::nodes::{MarkupNode}};
|
||||||
|
|
||||||
|
impl<'a> ToHtml<'a> for MarkupNode {
|
||||||
|
fn css_class(&self) -> Option<&'a str> {
|
||||||
|
Some("operator")
|
||||||
|
}
|
||||||
|
fn html_body(&self, buf: &mut bumpalo::collections::String<'a>) {
|
||||||
|
buf.push_str("MarkupNode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> ToHtml<'a> for Expr<'a> {
|
impl<'a> ToHtml<'a> for Expr<'a> {
|
||||||
fn css_class(&self) -> Option<&'a str> {
|
fn css_class(&self) -> Option<&'a str> {
|
||||||
|
@ -95,7 +104,8 @@ impl<'a> ToHtml<'a> for Expr<'a> {
|
||||||
}
|
}
|
||||||
Expr::Defs(defs, sub_expr) => {
|
Expr::Defs(defs, sub_expr) => {
|
||||||
for def_loc in defs.iter() {
|
for def_loc in defs.iter() {
|
||||||
def_loc.html(buf);
|
unimplemented!();
|
||||||
|
//def_loc.html(buf);
|
||||||
}
|
}
|
||||||
sub_expr.html(buf)
|
sub_expr.html(buf)
|
||||||
}
|
}
|
||||||
|
@ -160,14 +170,13 @@ impl<'a> ToHtml<'a> for ParamComma {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_expr_to_bump_str_html<'a>(
|
pub fn write_expr_to_bump_str_html<'a, 'b>(
|
||||||
arena: &mut Bump,
|
env: &mut lang::env::Env<'a>,
|
||||||
env: &mut Env<'a>,
|
scope: &mut lang::scope::Scope,
|
||||||
scope: &mut Scope,
|
|
||||||
region: Region,
|
region: Region,
|
||||||
expr: &'a Expr,
|
expr: &'a Expr,
|
||||||
interns: &Interns,
|
interns: &Interns,
|
||||||
bump_str: &mut bumpalo::collections::String<'a>
|
bump_str: &mut bumpalo::collections::String<'b>
|
||||||
) -> ASTResult<()> {
|
) -> ASTResult<()> {
|
||||||
let (expr2, _) = expr_to_expr2(env, scope, expr, region);
|
let (expr2, _) = expr_to_expr2(env, scope, expr, region);
|
||||||
|
|
||||||
|
@ -177,9 +186,8 @@ fn write_expr_to_bump_str_html<'a>(
|
||||||
let mut mark_node_pool = SlowPool::default();
|
let mut mark_node_pool = SlowPool::default();
|
||||||
|
|
||||||
let expr2_markup_id = expr2_to_markup(
|
let expr2_markup_id = expr2_to_markup(
|
||||||
arena,
|
|
||||||
env,
|
env,
|
||||||
&expr2,
|
&expr2_pool.get(expr2_id),
|
||||||
expr2_id,
|
expr2_id,
|
||||||
&mut mark_node_pool,
|
&mut mark_node_pool,
|
||||||
interns,
|
interns,
|
||||||
|
|
|
@ -2,7 +2,9 @@ use roc_region::all::Located;
|
||||||
|
|
||||||
pub trait ToHtml<'a> {
|
pub trait ToHtml<'a> {
|
||||||
fn css_class(&self) -> Option<&'a str>;
|
fn css_class(&self) -> Option<&'a str>;
|
||||||
|
|
||||||
fn html_body(&self, buf: &mut bumpalo::collections::String<'a>);
|
fn html_body(&self, buf: &mut bumpalo::collections::String<'a>);
|
||||||
|
|
||||||
fn html(&self, buf: &mut bumpalo::collections::String<'a>) {
|
fn html(&self, buf: &mut bumpalo::collections::String<'a>) {
|
||||||
let maybe_css_class = self.css_class();
|
let maybe_css_class = self.css_class();
|
||||||
|
|
||||||
|
|
199
docs/src/lib.rs
199
docs/src/lib.rs
|
@ -1,7 +1,9 @@
|
||||||
extern crate pulldown_cmark;
|
extern crate pulldown_cmark;
|
||||||
extern crate roc_load;
|
extern crate roc_load;
|
||||||
use crate::html::ToHtml;
|
use bumpalo::{collections::String as BumpString, collections::Vec as BumpVec, Bump};
|
||||||
use bumpalo::Bump;
|
use expr::write_expr_to_bump_str_html;
|
||||||
|
use roc_ast::lang;
|
||||||
|
use roc_ast::mem_pool::pool::Pool;
|
||||||
use roc_builtins::std::StdLib;
|
use roc_builtins::std::StdLib;
|
||||||
use roc_can::builtins::builtin_defs_map;
|
use roc_can::builtins::builtin_defs_map;
|
||||||
use roc_can::scope::Scope;
|
use roc_can::scope::Scope;
|
||||||
|
@ -10,10 +12,12 @@ use roc_load::docs::DocEntry::DocDef;
|
||||||
use roc_load::docs::{DocEntry, TypeAnnotation};
|
use roc_load::docs::{DocEntry, TypeAnnotation};
|
||||||
use roc_load::docs::{ModuleDocumentation, RecordField};
|
use roc_load::docs::{ModuleDocumentation, RecordField};
|
||||||
use roc_load::file::{LoadedModule, LoadingProblem};
|
use roc_load::file::{LoadedModule, LoadingProblem};
|
||||||
use roc_module::symbol::{IdentIds, Interns, ModuleId};
|
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds};
|
||||||
|
use roc_parse::ast::Expr;
|
||||||
use roc_parse::ident::{parse_ident, Ident};
|
use roc_parse::ident::{parse_ident, Ident};
|
||||||
use roc_parse::parser::{State, SyntaxError};
|
use roc_parse::parser::{State, SyntaxError};
|
||||||
use roc_region::all::Region;
|
use roc_region::all::Region;
|
||||||
|
use roc_types::subs::VarStore;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
@ -23,8 +27,8 @@ mod expr;
|
||||||
mod html;
|
mod html;
|
||||||
mod pattern;
|
mod pattern;
|
||||||
|
|
||||||
pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
|
pub fn generate_docs_html(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
|
||||||
let files_docs = files_to_documentations(filenames, std_lib);
|
let files_docs = load_modules_for_files(filenames, std_lib);
|
||||||
let mut arena = Bump::new();
|
let mut arena = Bump::new();
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -60,11 +64,11 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
|
||||||
.expect("TODO gracefully handle failing to make the favicon");
|
.expect("TODO gracefully handle failing to make the favicon");
|
||||||
|
|
||||||
let template_html = include_str!("./static/index.html")
|
let template_html = include_str!("./static/index.html")
|
||||||
.replace("<!-- search.js -->", &format!("{}search.js", base_href()))
|
.replace("<!-- search.js -->", &format!("{}search.js", base_url()))
|
||||||
.replace("<!-- styles.css -->", &format!("{}styles.css", base_href()))
|
.replace("<!-- styles.css -->", &format!("{}styles.css", base_url()))
|
||||||
.replace(
|
.replace(
|
||||||
"<!-- favicon.svg -->",
|
"<!-- favicon.svg -->",
|
||||||
&format!("{}favicon.svg", base_href()),
|
&format!("{}favicon.svg", base_url()),
|
||||||
)
|
)
|
||||||
.replace(
|
.replace(
|
||||||
"<!-- Module links -->",
|
"<!-- Module links -->",
|
||||||
|
@ -86,8 +90,8 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
|
||||||
for loaded_module in package.modules.iter_mut() {
|
for loaded_module in package.modules.iter_mut() {
|
||||||
arena.reset();
|
arena.reset();
|
||||||
|
|
||||||
let mut exports: bumpalo::collections::Vec<&str> =
|
let mut exports: BumpVec<&str> =
|
||||||
bumpalo::collections::Vec::with_capacity_in(loaded_module.exposed_values.len(), &arena);
|
BumpVec::with_capacity_in(loaded_module.exposed_values.len(), &arena);
|
||||||
|
|
||||||
// TODO should this also include exposed_aliases?
|
// TODO should this also include exposed_aliases?
|
||||||
for symbol in loaded_module.exposed_values.iter() {
|
for symbol in loaded_module.exposed_values.iter() {
|
||||||
|
@ -96,8 +100,8 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
|
||||||
|
|
||||||
let exports = exports.into_bump_slice();
|
let exports = exports.into_bump_slice();
|
||||||
|
|
||||||
for module in loaded_module.documentation.values_mut() {
|
for module_docs in loaded_module.documentation.values() {
|
||||||
let module_dir = build_dir.join(module.name.replace(".", "/").as_str());
|
let module_dir = build_dir.join(module_docs.name.replace(".", "/").as_str());
|
||||||
|
|
||||||
fs::create_dir_all(&module_dir)
|
fs::create_dir_all(&module_dir)
|
||||||
.expect("TODO gracefully handle not being able to create the module dir");
|
.expect("TODO gracefully handle not being able to create the module dir");
|
||||||
|
@ -111,11 +115,9 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
|
||||||
.replace(
|
.replace(
|
||||||
"<!-- Module Docs -->",
|
"<!-- Module Docs -->",
|
||||||
render_main_content(
|
render_main_content(
|
||||||
loaded_module.module_id,
|
|
||||||
exports,
|
exports,
|
||||||
&loaded_module.dep_idents,
|
module_docs,
|
||||||
&loaded_module.interns,
|
&loaded_module
|
||||||
module,
|
|
||||||
)
|
)
|
||||||
.as_str(),
|
.as_str(),
|
||||||
);
|
);
|
||||||
|
@ -128,17 +130,56 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
|
||||||
println!("🎉 Docs generated in {}", build_dir.display());
|
println!("🎉 Docs generated in {}", build_dir.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// html is written to buf
|
||||||
|
fn expr_to_html<'a>(buf: &mut BumpString<'a>, expr: Expr<'a>, env_module_id: ModuleId, env_module_ids: &'a ModuleIds, interns: &Interns) {
|
||||||
|
|
||||||
|
let mut env_pool = Pool::with_capacity(1024);
|
||||||
|
let mut env_arena = Bump::new();
|
||||||
|
|
||||||
|
let mut var_store = VarStore::default();
|
||||||
|
let dep_idents = IdentIds::exposed_builtins(8);
|
||||||
|
let exposed_ident_ids = IdentIds::default();
|
||||||
|
|
||||||
|
let mut env = lang::env::Env::new(
|
||||||
|
env_module_id,
|
||||||
|
&mut env_arena,
|
||||||
|
&mut env_pool,
|
||||||
|
&mut var_store,
|
||||||
|
dep_idents,
|
||||||
|
env_module_ids,
|
||||||
|
exposed_ident_ids,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut scope = lang::scope::Scope::new(env.home, env.pool, env.var_store);
|
||||||
|
let region = Region::new(0, 0, 0, 0);
|
||||||
|
|
||||||
|
// TODO remove unwrap
|
||||||
|
write_expr_to_bump_str_html(
|
||||||
|
&mut env,
|
||||||
|
&mut scope,
|
||||||
|
region,
|
||||||
|
&expr,
|
||||||
|
interns,
|
||||||
|
buf
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts plain text code to highlighted html
|
||||||
pub fn syntax_highlight_code<'a>(
|
pub fn syntax_highlight_code<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
buf: &mut bumpalo::collections::String<'a>,
|
buf: &mut BumpString<'a>,
|
||||||
code_str: &'a str,
|
code_str: &'a str,
|
||||||
|
env_module_id: ModuleId,
|
||||||
|
env_module_ids: &'a ModuleIds,
|
||||||
|
interns: &Interns
|
||||||
) -> Result<String, SyntaxError<'a>> {
|
) -> Result<String, SyntaxError<'a>> {
|
||||||
let trimmed_code_str = code_str.trim_end().trim();
|
let trimmed_code_str = code_str.trim_end().trim();
|
||||||
let state = State::new(trimmed_code_str.as_bytes());
|
let state = State::new(trimmed_code_str.as_bytes());
|
||||||
|
|
||||||
match roc_parse::expr::test_parse_expr(0, arena, state) {
|
match roc_parse::expr::test_parse_expr(0, arena, state) {
|
||||||
Ok(loc_expr) => {
|
Ok(loc_expr) => {
|
||||||
loc_expr.value.html(buf);
|
expr_to_html(buf, loc_expr.value, env_module_id, env_module_ids, interns);
|
||||||
|
|
||||||
Ok(buf.to_string())
|
Ok(buf.to_string())
|
||||||
}
|
}
|
||||||
Err(fail) => Err(SyntaxError::Expr(fail)),
|
Err(fail) => Err(SyntaxError::Expr(fail)),
|
||||||
|
@ -150,20 +191,19 @@ pub fn syntax_highlight_code<'a>(
|
||||||
// })
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO improve name, what is main content?
|
||||||
fn render_main_content(
|
fn render_main_content(
|
||||||
home: ModuleId,
|
|
||||||
exposed_values: &[&str],
|
exposed_values: &[&str],
|
||||||
dep_idents: &MutMap<ModuleId, IdentIds>,
|
module: &ModuleDocumentation,
|
||||||
interns: &Interns,
|
loaded_module: &LoadedModule,
|
||||||
module: &mut ModuleDocumentation,
|
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
|
||||||
buf.push_str(
|
buf.push_str(
|
||||||
html_node(
|
html_to_string(
|
||||||
"h2",
|
"h2",
|
||||||
vec![("class", "module-name")],
|
vec![("class", "module-name")],
|
||||||
html_node("a", vec![("href", "/#")], module.name.as_str()).as_str(),
|
html_to_string("a", vec![("href", "/#")], module.name.as_str()).as_str(),
|
||||||
)
|
)
|
||||||
.as_str(),
|
.as_str(),
|
||||||
);
|
);
|
||||||
|
@ -187,7 +227,7 @@ fn render_main_content(
|
||||||
|
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
|
|
||||||
content.push_str(html_node("a", vec![("href", href.as_str())], name).as_str());
|
content.push_str(html_to_string("a", vec![("href", href.as_str())], name).as_str());
|
||||||
|
|
||||||
for type_var in &doc_def.type_vars {
|
for type_var in &doc_def.type_vars {
|
||||||
content.push(' ');
|
content.push(' ');
|
||||||
|
@ -206,7 +246,7 @@ fn render_main_content(
|
||||||
type_annotation_to_html(0, &mut content, type_ann);
|
type_annotation_to_html(0, &mut content, type_ann);
|
||||||
|
|
||||||
buf.push_str(
|
buf.push_str(
|
||||||
html_node(
|
html_to_string(
|
||||||
"h3",
|
"h3",
|
||||||
vec![("id", name), ("class", "entry-name")],
|
vec![("id", name), ("class", "entry-name")],
|
||||||
content.as_str(),
|
content.as_str(),
|
||||||
|
@ -217,12 +257,10 @@ fn render_main_content(
|
||||||
if let Some(docs) = &doc_def.docs {
|
if let Some(docs) = &doc_def.docs {
|
||||||
buf.push_str(
|
buf.push_str(
|
||||||
markdown_to_html(
|
markdown_to_html(
|
||||||
home,
|
|
||||||
exposed_values,
|
exposed_values,
|
||||||
dep_idents,
|
&module.scope,
|
||||||
&mut module.scope,
|
|
||||||
interns,
|
|
||||||
docs.to_string(),
|
docs.to_string(),
|
||||||
|
loaded_module,
|
||||||
)
|
)
|
||||||
.as_str(),
|
.as_str(),
|
||||||
);
|
);
|
||||||
|
@ -230,12 +268,10 @@ fn render_main_content(
|
||||||
}
|
}
|
||||||
DocEntry::DetachedDoc(docs) => {
|
DocEntry::DetachedDoc(docs) => {
|
||||||
let markdown = markdown_to_html(
|
let markdown = markdown_to_html(
|
||||||
home,
|
|
||||||
exposed_values,
|
exposed_values,
|
||||||
dep_idents,
|
&module.scope,
|
||||||
&mut module.scope,
|
|
||||||
interns,
|
|
||||||
docs.to_string(),
|
docs.to_string(),
|
||||||
|
loaded_module,
|
||||||
);
|
);
|
||||||
buf.push_str(markdown.as_str());
|
buf.push_str(markdown.as_str());
|
||||||
}
|
}
|
||||||
|
@ -246,7 +282,7 @@ fn render_main_content(
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
fn html_node(tag_name: &str, attrs: Vec<(&str, &str)>, content: &str) -> String {
|
fn html_to_string(tag_name: &str, attrs: Vec<(&str, &str)>, content: &str) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
|
||||||
buf.push('<');
|
buf.push('<');
|
||||||
|
@ -275,62 +311,62 @@ fn html_node(tag_name: &str, attrs: Vec<(&str, &str)>, content: &str) -> String
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base_href() -> String {
|
fn base_url() -> String {
|
||||||
// e.g. "builtins/" in "https://roc-lang.org/builtins/Str"
|
// e.g. "builtins/" in "https://roc-lang.org/builtins/Str"
|
||||||
//
|
//
|
||||||
// TODO make this a CLI flag to the `docs` subcommand instead of an env var
|
// TODO make this a CLI flag to the `docs` subcommand instead of an env var
|
||||||
match std::env::var("ROC_DOCS_URL_ROOT") {
|
match std::env::var("ROC_DOCS_URL_ROOT") {
|
||||||
Ok(root_builtins_path) => {
|
Ok(root_builtins_path) => {
|
||||||
let mut href = String::with_capacity(root_builtins_path.len() + 64);
|
let mut url_str = String::with_capacity(root_builtins_path.len() + 64);
|
||||||
|
|
||||||
if !root_builtins_path.starts_with('/') {
|
if !root_builtins_path.starts_with('/') {
|
||||||
href.push('/');
|
url_str.push('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
href.push_str(&root_builtins_path);
|
url_str.push_str(&root_builtins_path);
|
||||||
|
|
||||||
if !root_builtins_path.ends_with('/') {
|
if !root_builtins_path.ends_with('/') {
|
||||||
href.push('/');
|
url_str.push('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
href
|
url_str
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut href = String::with_capacity(64);
|
let mut url_str = String::with_capacity(64);
|
||||||
|
|
||||||
href.push('/');
|
url_str.push('/');
|
||||||
|
|
||||||
href
|
url_str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_name_and_version(name: &str, version: &str) -> String {
|
fn render_name_and_version(name: &str, version: &str) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let mut href = base_href();
|
let mut url_str = base_url();
|
||||||
|
|
||||||
href.push_str(name);
|
url_str.push_str(name);
|
||||||
|
|
||||||
buf.push_str(
|
buf.push_str(
|
||||||
html_node(
|
html_to_string(
|
||||||
"h1",
|
"h1",
|
||||||
vec![("class", "pkg-full-name")],
|
vec![("class", "pkg-full-name")],
|
||||||
html_node("a", vec![("href", href.as_str())], name).as_str(),
|
html_to_string("a", vec![("href", url_str.as_str())], name).as_str(),
|
||||||
)
|
)
|
||||||
.as_str(),
|
.as_str(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut versions_href = base_href();
|
let mut versions_url_str = base_url();
|
||||||
|
|
||||||
versions_href.push('/');
|
versions_url_str.push('/');
|
||||||
versions_href.push_str(name);
|
versions_url_str.push_str(name);
|
||||||
versions_href.push('/');
|
versions_url_str.push('/');
|
||||||
versions_href.push_str(version);
|
versions_url_str.push_str(version);
|
||||||
|
|
||||||
buf.push_str(
|
buf.push_str(
|
||||||
html_node(
|
html_to_string(
|
||||||
"a",
|
"a",
|
||||||
vec![("class", "version"), ("href", versions_href.as_str())],
|
vec![("class", "version"), ("href", versions_url_str.as_str())],
|
||||||
version,
|
version,
|
||||||
)
|
)
|
||||||
.as_str(),
|
.as_str(),
|
||||||
|
@ -350,13 +386,13 @@ fn render_sidebar<'a, I: Iterator<Item = (Vec<String>, &'a ModuleDocumentation)>
|
||||||
let name = module.name.as_str();
|
let name = module.name.as_str();
|
||||||
|
|
||||||
let href = {
|
let href = {
|
||||||
let mut href_buf = base_href();
|
let mut href_buf = base_url();
|
||||||
href_buf.push_str(name);
|
href_buf.push_str(name);
|
||||||
href_buf
|
href_buf
|
||||||
};
|
};
|
||||||
|
|
||||||
sidebar_entry_content.push_str(
|
sidebar_entry_content.push_str(
|
||||||
html_node(
|
html_to_string(
|
||||||
"a",
|
"a",
|
||||||
vec![("class", "sidebar-module-link"), ("href", href.as_str())],
|
vec![("class", "sidebar-module-link"), ("href", href.as_str())],
|
||||||
name,
|
name,
|
||||||
|
@ -377,7 +413,7 @@ fn render_sidebar<'a, I: Iterator<Item = (Vec<String>, &'a ModuleDocumentation)>
|
||||||
entry_href.push_str(doc_def.name.as_str());
|
entry_href.push_str(doc_def.name.as_str());
|
||||||
|
|
||||||
entries_buf.push_str(
|
entries_buf.push_str(
|
||||||
html_node(
|
html_to_string(
|
||||||
"a",
|
"a",
|
||||||
vec![("href", entry_href.as_str())],
|
vec![("href", entry_href.as_str())],
|
||||||
doc_def.name.as_str(),
|
doc_def.name.as_str(),
|
||||||
|
@ -392,7 +428,7 @@ fn render_sidebar<'a, I: Iterator<Item = (Vec<String>, &'a ModuleDocumentation)>
|
||||||
};
|
};
|
||||||
|
|
||||||
sidebar_entry_content.push_str(
|
sidebar_entry_content.push_str(
|
||||||
html_node(
|
html_to_string(
|
||||||
"div",
|
"div",
|
||||||
vec![("class", "sidebar-sub-entries")],
|
vec![("class", "sidebar-sub-entries")],
|
||||||
entries.as_str(),
|
entries.as_str(),
|
||||||
|
@ -401,7 +437,7 @@ fn render_sidebar<'a, I: Iterator<Item = (Vec<String>, &'a ModuleDocumentation)>
|
||||||
);
|
);
|
||||||
|
|
||||||
buf.push_str(
|
buf.push_str(
|
||||||
html_node(
|
html_to_string(
|
||||||
"div",
|
"div",
|
||||||
vec![("class", "sidebar-entry")],
|
vec![("class", "sidebar-entry")],
|
||||||
sidebar_entry_content.as_str(),
|
sidebar_entry_content.as_str(),
|
||||||
|
@ -413,9 +449,9 @@ fn render_sidebar<'a, I: Iterator<Item = (Vec<String>, &'a ModuleDocumentation)>
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn files_to_documentations(filenames: Vec<PathBuf>, std_lib: StdLib) -> Vec<LoadedModule> {
|
pub fn load_modules_for_files(filenames: Vec<PathBuf>, std_lib: StdLib) -> Vec<LoadedModule> {
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let mut files_docs = vec![];
|
let mut modules = vec![];
|
||||||
|
|
||||||
for filename in filenames {
|
for filename in filenames {
|
||||||
let mut src_dir = filename.clone();
|
let mut src_dir = filename.clone();
|
||||||
|
@ -430,7 +466,7 @@ pub fn files_to_documentations(filenames: Vec<PathBuf>, std_lib: StdLib) -> Vec<
|
||||||
std::mem::size_of::<usize>() as u32, // This is just type-checking for docs, so "target" doesn't matter
|
std::mem::size_of::<usize>() as u32, // This is just type-checking for docs, so "target" doesn't matter
|
||||||
builtin_defs_map,
|
builtin_defs_map,
|
||||||
) {
|
) {
|
||||||
Ok(loaded) => files_docs.push(loaded),
|
Ok(loaded) => modules.push(loaded),
|
||||||
Err(LoadingProblem::FormattedReport(report)) => {
|
Err(LoadingProblem::FormattedReport(report)) => {
|
||||||
println!("{}", report);
|
println!("{}", report);
|
||||||
panic!();
|
panic!();
|
||||||
|
@ -439,7 +475,7 @@ pub fn files_to_documentations(filenames: Vec<PathBuf>, std_lib: StdLib) -> Vec<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
files_docs
|
modules
|
||||||
}
|
}
|
||||||
|
|
||||||
const INDENT: &str = " ";
|
const INDENT: &str = " ";
|
||||||
|
@ -454,6 +490,7 @@ fn new_line(buf: &mut String) {
|
||||||
buf.push('\n');
|
buf.push('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// html is written to buf
|
||||||
fn type_annotation_to_html(indent_level: usize, buf: &mut String, type_ann: &TypeAnnotation) {
|
fn type_annotation_to_html(indent_level: usize, buf: &mut String, type_ann: &TypeAnnotation) {
|
||||||
let is_multiline = should_be_multiline(type_ann);
|
let is_multiline = should_be_multiline(type_ann);
|
||||||
match type_ann {
|
match type_ann {
|
||||||
|
@ -715,7 +752,7 @@ fn doc_url<'a>(
|
||||||
home: ModuleId,
|
home: ModuleId,
|
||||||
exposed_values: &[&str],
|
exposed_values: &[&str],
|
||||||
dep_idents: &MutMap<ModuleId, IdentIds>,
|
dep_idents: &MutMap<ModuleId, IdentIds>,
|
||||||
scope: &mut Scope,
|
scope: &Scope,
|
||||||
interns: &'a Interns,
|
interns: &'a Interns,
|
||||||
mut module_name: &'a str,
|
mut module_name: &'a str,
|
||||||
ident: &str,
|
ident: &str,
|
||||||
|
@ -782,7 +819,7 @@ fn doc_url<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut url = base_href();
|
let mut url = base_url();
|
||||||
|
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
|
@ -798,12 +835,10 @@ fn doc_url<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn markdown_to_html(
|
fn markdown_to_html(
|
||||||
home: ModuleId,
|
|
||||||
exposed_values: &[&str],
|
exposed_values: &[&str],
|
||||||
dep_idents: &MutMap<ModuleId, IdentIds>,
|
scope: &Scope,
|
||||||
scope: &mut Scope,
|
|
||||||
interns: &Interns,
|
|
||||||
markdown: String,
|
markdown: String,
|
||||||
|
loaded_module: &LoadedModule,
|
||||||
) -> String {
|
) -> String {
|
||||||
use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Tag::*};
|
use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Tag::*};
|
||||||
|
|
||||||
|
@ -830,11 +865,11 @@ fn markdown_to_html(
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
Some(symbol_name) if iter.next().is_none() => {
|
Some(symbol_name) if iter.next().is_none() => {
|
||||||
let DocUrl { url, title } = doc_url(
|
let DocUrl { url, title } = doc_url(
|
||||||
home,
|
loaded_module.module_id,
|
||||||
exposed_values,
|
exposed_values,
|
||||||
dep_idents,
|
&loaded_module.dep_idents,
|
||||||
scope,
|
scope,
|
||||||
interns,
|
&loaded_module.interns,
|
||||||
module_name,
|
module_name,
|
||||||
symbol_name,
|
symbol_name,
|
||||||
);
|
);
|
||||||
|
@ -853,11 +888,11 @@ fn markdown_to_html(
|
||||||
// This looks like a global tag name, but it could
|
// This looks like a global tag name, but it could
|
||||||
// be a type alias that's in scope, e.g. [I64]
|
// be a type alias that's in scope, e.g. [I64]
|
||||||
let DocUrl { url, title } = doc_url(
|
let DocUrl { url, title } = doc_url(
|
||||||
home,
|
loaded_module.module_id,
|
||||||
exposed_values,
|
exposed_values,
|
||||||
dep_idents,
|
&loaded_module.dep_idents,
|
||||||
scope,
|
scope,
|
||||||
interns,
|
&loaded_module.interns,
|
||||||
"",
|
"",
|
||||||
type_name,
|
type_name,
|
||||||
);
|
);
|
||||||
|
@ -961,8 +996,16 @@ fn markdown_to_html(
|
||||||
Event::Text(CowStr::Borrowed(code_str)) if expecting_code_block => {
|
Event::Text(CowStr::Borrowed(code_str)) if expecting_code_block => {
|
||||||
let code_block_arena = Bump::new();
|
let code_block_arena = Bump::new();
|
||||||
|
|
||||||
let mut code_block_buf = bumpalo::collections::String::new_in(&code_block_arena);
|
let mut code_block_buf = BumpString::new_in(&code_block_arena);
|
||||||
match syntax_highlight_code(&code_block_arena, &mut code_block_buf, code_str) {
|
match syntax_highlight_code(
|
||||||
|
&code_block_arena,
|
||||||
|
&mut code_block_buf,
|
||||||
|
code_str,
|
||||||
|
loaded_module.module_id,
|
||||||
|
&loaded_module.interns.module_ids,
|
||||||
|
&loaded_module.interns
|
||||||
|
)
|
||||||
|
{
|
||||||
Ok(highlighted_code_str) => {
|
Ok(highlighted_code_str) => {
|
||||||
docs_parser.push(Event::Html(CowStr::from(highlighted_code_str)));
|
docs_parser.push(Event::Html(CowStr::from(highlighted_code_str)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ extern crate pretty_assertions;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod insert_doc_syntax_highlighting {
|
mod insert_doc_syntax_highlighting {
|
||||||
use bumpalo::Bump;
|
use bumpalo::{collections::String as BumpString, Bump};
|
||||||
use roc_can::env::Env;
|
use roc_can::env::Env;
|
||||||
use roc_can::scope::Scope;
|
use roc_can::scope::Scope;
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
|
@ -14,8 +14,24 @@ mod insert_doc_syntax_highlighting {
|
||||||
fn expect_html(code_str: &str, want: &str) {
|
fn expect_html(code_str: &str, want: &str) {
|
||||||
let code_block_arena = Bump::new();
|
let code_block_arena = Bump::new();
|
||||||
|
|
||||||
let mut code_block_buf = bumpalo::collections::String::new_in(&code_block_arena);
|
|
||||||
match syntax_highlight_code(&code_block_arena, &mut code_block_buf, code_str) {
|
let mut module_ids = ModuleIds::default();
|
||||||
|
let mod_id = module_ids.get_or_insert(&"ModId123".into());
|
||||||
|
|
||||||
|
let interns = Interns {
|
||||||
|
module_ids: module_ids.clone(),
|
||||||
|
all_ident_ids: IdentIds::exposed_builtins(8),
|
||||||
|
};
|
||||||
|
let mut code_block_buf = BumpString::new_in(&code_block_arena);
|
||||||
|
|
||||||
|
match syntax_highlight_code(
|
||||||
|
&code_block_arena,
|
||||||
|
&mut code_block_buf,
|
||||||
|
code_str,
|
||||||
|
mod_id,
|
||||||
|
&module_ids,
|
||||||
|
&interns
|
||||||
|
) {
|
||||||
Ok(highlighted_code_str) => {
|
Ok(highlighted_code_str) => {
|
||||||
assert_eq!(highlighted_code_str, want);
|
assert_eq!(highlighted_code_str, want);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +41,7 @@ mod insert_doc_syntax_highlighting {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
/*#[test]
|
||||||
fn simple_code_block() {
|
fn simple_code_block() {
|
||||||
expect_html(
|
expect_html(
|
||||||
r#"
|
r#"
|
||||||
|
@ -43,24 +59,17 @@ mod insert_doc_syntax_highlighting {
|
||||||
<div class="syntax-number">2</div>
|
<div class="syntax-number">2</div>
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple_code_block() {
|
||||||
|
expect_html(
|
||||||
|
r#"
|
||||||
|
2
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
<div class="syntax-number">2</div>
|
||||||
|
"#,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// #[test]
|
|
||||||
// fn simple_code_block() {
|
|
||||||
// expect_html(
|
|
||||||
// r#"
|
|
||||||
// x : Nat
|
|
||||||
// x =
|
|
||||||
// 4
|
|
||||||
//
|
|
||||||
// 2
|
|
||||||
// "#,
|
|
||||||
// r#"
|
|
||||||
// <div class="syntax-var">x</div> <div class="syntax-operator">:</div> <div class="syntax-type">Nat</div>
|
|
||||||
// <div class="syntax-var">x</div> <div class="syntax-operator">=</div>
|
|
||||||
// <div class="syntax-number">4</div>
|
|
||||||
//
|
|
||||||
// <div class="syntax-number">2</div>
|
|
||||||
// "#,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,6 @@ pub fn init_model<'a>(
|
||||||
EmptyCodeString {}.fail()
|
EmptyCodeString {}.fail()
|
||||||
} else {
|
} else {
|
||||||
Ok(ast_to_mark_nodes(
|
Ok(ast_to_mark_nodes(
|
||||||
code_arena,
|
|
||||||
&mut module.env,
|
&mut module.env,
|
||||||
&module.ast,
|
&module.ast,
|
||||||
&mut mark_node_pool,
|
&mut mark_node_pool,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue