docs flow working with mocked markup to html

This commit is contained in:
Anton-4 2021-10-01 18:22:27 +02:00
parent 28cf11a1d9
commit f63c276a5f
9 changed files with 178 additions and 135 deletions

View file

@ -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"),

View file

@ -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);

View file

@ -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(

View file

@ -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;

View file

@ -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,

View file

@ -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();

View file

@ -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)));
} }

View file

@ -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>
// "#,
// );
// }
} }

View file

@ -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,