Merge pull request #1759 from rtfeldman/docs_markup

re-use editor markup for docs
This commit is contained in:
Richard Feldman 2021-10-07 22:31:46 -04:00 committed by GitHub
commit ced76a6a31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 676 additions and 179 deletions

7
Cargo.lock generated
View file

@ -3228,8 +3228,10 @@ dependencies = [
"libc",
"page_size",
"pretty_assertions 0.6.1",
"roc_builtins",
"roc_can",
"roc_collections",
"roc_load",
"roc_module",
"roc_parse",
"roc_problem",
@ -3414,14 +3416,19 @@ dependencies = [
"maplit",
"pretty_assertions 0.5.1",
"pulldown-cmark",
"roc_ast",
"roc_builtins",
"roc_can",
"roc_code_markup",
"roc_collections",
"roc_fmt",
"roc_load",
"roc_module",
"roc_parse",
"roc_region",
"roc_types",
"tempfile",
"uuid",
]
[[package]]

View file

@ -7,6 +7,7 @@ edition = "2018"
description = "AST as used by the editor and (soon) docs. In contrast to the compiler, these types do not keep track of a location in a file."
[dependencies]
roc_builtins = { path = "../compiler/builtins"}
roc_can = { path = "../compiler/can" }
roc_collections = { path = "../compiler/collections" }
roc_region = { path = "../compiler/region" }
@ -15,6 +16,7 @@ roc_parse = { path = "../compiler/parse" }
roc_problem = { path = "../compiler/problem" }
roc_types = { path = "../compiler/types" }
roc_unify = { path = "../compiler/unify"}
roc_load = { path = "../compiler/load" }
arraystring = "0.3.0"
bumpalo = { version = "3.6.1", features = ["collections"] }
libc = "0.2"

View file

@ -9,7 +9,7 @@ use crate::{
def::def::References,
expr::{
expr2::{Expr2, ExprId, WhenBranch},
expr_to_expr2::to_expr2,
expr_to_expr2::expr_to_expr2,
output::Output,
record_field::RecordField,
},
@ -147,7 +147,8 @@ fn canonicalize_field<'a>(
// Both a label and a value, e.g. `{ name: "blah" }`
RequiredValue(label, _, loc_expr) => {
let field_var = env.var_store.fresh();
let (loc_can_expr, output) = to_expr2(env, scope, &loc_expr.value, loc_expr.region);
let (loc_can_expr, output) =
expr_to_expr2(env, scope, &loc_expr.value, loc_expr.region);
Ok(CanonicalField::LabelAndValue {
label: label.value,
@ -211,7 +212,7 @@ pub(crate) fn canonicalize_when_branch<'a>(
}
let (value, mut branch_output) =
to_expr2(env, &mut scope, &branch.value.value, branch.value.region);
expr_to_expr2(env, &mut scope, &branch.value.value, branch.value.region);
let value_id = env.pool.add(value);
env.set_region(value_id, branch.value.region);
@ -219,7 +220,7 @@ pub(crate) fn canonicalize_when_branch<'a>(
None => None,
Some(loc_expr) => {
let (can_guard, guard_branch_output) =
to_expr2(env, &mut scope, &loc_expr.value, loc_expr.region);
expr_to_expr2(env, &mut scope, &loc_expr.value, loc_expr.region);
let expr_id = env.pool.add(can_guard);
env.set_region(expr_id, loc_expr.region);

View file

@ -27,7 +27,7 @@ use ven_graph::{strongly_connected_components, topological_sort_into_groups};
use crate::{
lang::{
core::{
expr::{expr2::Expr2, expr_to_expr2::to_expr2, output::Output},
expr::{expr2::Expr2, expr_to_expr2::expr_to_expr2, output::Output},
fun_def::FunctionDef,
pattern::{self, symbols_from_pattern, to_pattern_id, Pattern2, PatternId},
types::{to_annotation2, Alias, Annotation2, Signature, Type2, TypeId},
@ -472,7 +472,7 @@ fn canonicalize_pending_def<'a>(
};
let (loc_can_expr, can_output) =
to_expr2(env, scope, &loc_expr.value, loc_expr.region);
expr_to_expr2(env, scope, &loc_expr.value, loc_expr.region);
output.references.union_mut(can_output.references.clone());
@ -639,7 +639,8 @@ fn canonicalize_pending_def<'a>(
env.closure_name_symbol = Some(*defined_symbol);
};
let (loc_can_expr, can_output) = to_expr2(env, scope, &loc_expr.value, loc_expr.region);
let (loc_can_expr, can_output) =
expr_to_expr2(env, scope, &loc_expr.value, loc_expr.region);
output.references.union_mut(can_output.references.clone());

View file

@ -20,11 +20,11 @@ pub fn defs_to_defs2<'a>(
) -> Vec<Def2> {
parsed_defs
.iter()
.map(|loc| to_def2_from_def(arena, env, scope, &loc.value, region))
.map(|loc| def_to_def2(arena, env, scope, &loc.value, region))
.collect()
}
pub fn to_def2_from_def<'a>(
pub fn def_to_def2<'a>(
arena: &'a Bump,
env: &mut Env<'a>,
scope: &mut Scope,
@ -34,8 +34,8 @@ pub fn to_def2_from_def<'a>(
use roc_parse::ast::Def::*;
match parsed_def {
SpaceBefore(inner_def, _) => to_def2_from_def(arena, env, scope, inner_def, region),
SpaceAfter(inner_def, _) => to_def2_from_def(arena, env, scope, inner_def, region),
SpaceBefore(inner_def, _) => def_to_def2(arena, env, scope, inner_def, region),
SpaceAfter(inner_def, _) => def_to_def2(arena, env, scope, inner_def, region),
Body(&loc_pattern, &loc_expr) => {
// TODO loc_pattern use identifier
let expr2 = loc_expr_to_expr2(arena, loc_expr, env, scope, region).0;

View file

@ -36,12 +36,12 @@ pub fn loc_expr_to_expr2<'a>(
) -> (Expr2, Output) {
let desugared_loc_expr = desugar_expr(arena, arena.alloc(loc_expr));
to_expr2(env, scope, arena.alloc(desugared_loc_expr.value), region)
expr_to_expr2(env, scope, arena.alloc(desugared_loc_expr.value), region)
}
const ZERO: Region = Region::zero();
pub fn to_expr2<'a>(
pub fn expr_to_expr2<'a>(
env: &mut Env<'a>,
scope: &mut Scope,
parse_expr: &'a roc_parse::ast::Expr<'a>,
@ -139,7 +139,7 @@ pub fn to_expr2<'a>(
let elems: PoolVec<ExprId> = PoolVec::with_capacity(items.len() as u32, env.pool);
for (node_id, item) in elems.iter_node_ids().zip(items.iter()) {
let (expr, sub_output) = to_expr2(env, scope, &item.value, item.region);
let (expr, sub_output) = expr_to_expr2(env, scope, &item.value, item.region);
output_ref.union(sub_output);
@ -188,7 +188,7 @@ pub fn to_expr2<'a>(
final_comments: _,
} => {
let (can_update, update_out) =
to_expr2(env, scope, &loc_update.value, loc_update.region);
expr_to_expr2(env, scope, &loc_update.value, loc_update.region);
if let Expr2::Var(symbol) = &can_update {
match canonicalize_fields(env, scope, fields) {
@ -309,10 +309,11 @@ pub fn to_expr2<'a>(
let mut output = Output::default();
for (condition, then_branch) in branches.iter() {
let (cond, cond_output) = to_expr2(env, scope, &condition.value, condition.region);
let (cond, cond_output) =
expr_to_expr2(env, scope, &condition.value, condition.region);
let (then_expr, then_output) =
to_expr2(env, scope, &then_branch.value, then_branch.region);
expr_to_expr2(env, scope, &then_branch.value, then_branch.region);
output.references.union_mut(cond_output.references);
output.references.union_mut(then_output.references);
@ -321,7 +322,7 @@ pub fn to_expr2<'a>(
}
let (else_expr, else_output) =
to_expr2(env, scope, &final_else.value, final_else.region);
expr_to_expr2(env, scope, &final_else.value, final_else.region);
output.references.union_mut(else_output.references);
@ -338,7 +339,8 @@ pub fn to_expr2<'a>(
When(loc_cond, branches) => {
// Infer the condition expression's type.
let cond_var = env.var_store.fresh();
let (can_cond, mut output) = to_expr2(env, scope, &loc_cond.value, loc_cond.region);
let (can_cond, mut output) =
expr_to_expr2(env, scope, &loc_cond.value, loc_cond.region);
// the condition can never be a tail-call
output.tail_call = None;
@ -411,7 +413,7 @@ pub fn to_expr2<'a>(
}
let (body_expr, new_output) =
to_expr2(env, &mut scope, &loc_body_expr.value, loc_body_expr.region);
expr_to_expr2(env, &mut scope, &loc_body_expr.value, loc_body_expr.region);
let mut captured_symbols: MutSet<Symbol> =
new_output.references.lookups.iter().copied().collect();
@ -501,7 +503,7 @@ pub fn to_expr2<'a>(
let fn_region = loc_fn.region;
// Canonicalize the function expression and its arguments
let (fn_expr, mut output) = to_expr2(env, scope, &loc_fn.value, fn_region);
let (fn_expr, mut output) = expr_to_expr2(env, scope, &loc_fn.value, fn_region);
// The function's return type
let args = PoolVec::with_capacity(loc_args.len() as u32, env.pool);
@ -592,7 +594,8 @@ pub fn to_expr2<'a>(
// The def as a whole is a tail call iff its return expression is a tail call.
// Use its output as a starting point because its tail_call already has the right answer!
let (ret_expr, mut output) = to_expr2(env, &mut scope, &loc_ret.value, loc_ret.region);
let (ret_expr, mut output) =
expr_to_expr2(env, &mut scope, &loc_ret.value, loc_ret.region);
output
.introduced_variables
@ -704,7 +707,7 @@ pub fn to_expr_id<'a>(
parse_expr: &'a roc_parse::ast::Expr<'a>,
region: Region,
) -> (ExprId, Output) {
let (expr, output) = to_expr2(env, scope, parse_expr, region);
let (expr, output) = expr_to_expr2(env, scope, parse_expr, region);
(env.add(expr, region), output)
}

View file

@ -1,6 +1,6 @@
pub mod expr2;
pub mod expr2_to_string;
pub(crate) mod expr_to_expr2;
pub mod expr_to_expr2;
mod introduced_vars;
pub(crate) mod output;
pub mod record_field;

View file

@ -3,7 +3,7 @@ use roc_parse::ast::StrLiteral;
use crate::{
ast_error::{ASTResult, UnexpectedASTNode},
lang::{core::expr::expr_to_expr2::to_expr2, env::Env, scope::Scope},
lang::{core::expr::expr_to_expr2::expr_to_expr2, env::Env, scope::Scope},
mem_pool::{pool::Pool, pool_str::PoolStr, pool_vec::PoolVec},
};
@ -94,7 +94,7 @@ fn flatten_str_lines<'a>(
}
let (loc_expr, new_output) =
to_expr2(env, scope, loc_expr.value, loc_expr.region);
expr_to_expr2(env, scope, loc_expr.value, loc_expr.region);
output.union(new_output);

View file

@ -3,5 +3,6 @@ mod canonicalization;
pub mod constrain;
pub mod lang;
pub mod mem_pool;
pub mod module;
pub mod parse;
pub mod solve_type;

39
ast/src/module.rs Normal file
View file

@ -0,0 +1,39 @@
use std::path::Path;
use bumpalo::Bump;
use roc_collections::all::MutMap;
use roc_load::file::LoadedModule;
pub fn load_module(src_file: &Path) -> LoadedModule {
let subs_by_module = MutMap::default();
let arena = Bump::new();
let loaded = roc_load::file::load_and_typecheck(
&arena,
src_file.to_path_buf(),
arena.alloc(roc_builtins::std::standard_stdlib()),
src_file.parent().unwrap_or_else(|| {
panic!(
"src_file {:?} did not have a parent directory but I need to have one.",
src_file
)
}),
subs_by_module,
8,
roc_can::builtins::builtin_defs_map,
);
match loaded {
Ok(x) => x,
Err(roc_load::file::LoadingProblem::FormattedReport(report)) => {
panic!(
"Failed to load module from src_file {:?}. Report: {:?}",
src_file, report
);
}
Err(e) => panic!(
"Failed to load module from src_file {:?}: {:?}",
src_file, e
),
}
}

View file

@ -240,7 +240,7 @@ pub fn build_app<'a>() -> App<'a> {
}
pub fn docs(files: Vec<PathBuf>) {
roc_docs::generate(
roc_docs::generate_docs_html(
files,
roc_builtins::std::standard_stdlib(),
Path::new("./generated-docs"),

View file

@ -19,7 +19,7 @@ pub fn new_comma_mn(expr_id: ExprId, parent_id_opt: Option<MarkNodeId>) -> Marku
MarkupNode::Text {
content: nodes::COMMA.to_owned(),
ast_node_id: ASTNodeId::AExprId(expr_id),
syn_high_style: HighlightStyle::Blank,
syn_high_style: HighlightStyle::Comma,
attributes: Attributes::default(),
parent_id_opt,
newlines_at_end: 0,

View file

@ -13,7 +13,6 @@ use super::{
};
use crate::markup_error::{ExpectedTextNode, NestedNodeMissingChild, NestedNodeRequired};
use bumpalo::Bump;
use roc_ast::{
ast_error::ASTResult,
lang::{
@ -305,9 +304,8 @@ fn new_markup_node(
mark_node_pool.add(node)
}
pub fn def2_to_markup<'a, 'b>(
arena: &'a Bump,
env: &mut Env<'b>,
pub fn def2_to_markup<'a>(
env: &mut Env<'a>,
def2: &Def2,
def2_node_id: DefId,
mark_node_pool: &mut SlowPool,
@ -321,7 +319,6 @@ pub fn def2_to_markup<'a, 'b>(
expr_id,
} => {
let expr_mn_id = expr2_to_markup(
arena,
env,
env.pool.get(*expr_id),
*expr_id,
@ -347,9 +344,8 @@ pub fn def2_to_markup<'a, 'b>(
}
// make Markup Nodes: generate String representation, assign Highlighting Style
pub fn expr2_to_markup<'a, 'b>(
arena: &'a Bump,
env: &mut Env<'b>,
pub fn expr2_to_markup<'a>(
env: &mut Env<'a>,
expr2: &Expr2,
expr2_node_id: ExprId,
mark_node_pool: &mut SlowPool,
@ -380,7 +376,7 @@ pub fn expr2_to_markup<'a, 'b>(
),
Expr2::Call { expr: 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) => {
//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);
children_ids.push(expr2_to_markup(
arena,
env,
sub_expr2,
*node_id,
@ -460,7 +455,6 @@ pub fn expr2_to_markup<'a, 'b>(
let sub_expr2 = env.pool.get(*sub_expr2_node_id);
children_ids.push(expr2_to_markup(
arena,
env,
sub_expr2,
*sub_expr2_node_id,
@ -520,7 +514,6 @@ pub fn expr2_to_markup<'a, 'b>(
expr_var: _,
} => {
let body_mn_id = expr2_to_markup(
arena,
env,
env.pool.get(*expr_id),
*expr_id,
@ -797,9 +790,8 @@ fn add_header_mn_list(
.collect()
}
pub fn ast_to_mark_nodes<'a, 'b>(
arena: &'a Bump,
env: &mut Env<'b>,
pub fn ast_to_mark_nodes<'a>(
env: &mut Env<'a>,
ast: &AST,
mark_node_pool: &mut SlowPool,
interns: &Interns,
@ -809,11 +801,11 @@ pub fn ast_to_mark_nodes<'a, 'b>(
for &def_id in ast.def_ids.iter() {
let def2 = env.pool.get(def_id);
let expr2_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(expr2_markup_id, mark_node_pool);
set_parent_for_all(def2_markup_id, mark_node_pool);
all_mark_node_ids.push(expr2_markup_id);
all_mark_node_ids.push(def2_markup_id);
}
Ok(all_mark_node_ids)

View file

@ -6,6 +6,7 @@ use crate::colors::{self, from_hsb, RgbaTup};
#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug, Deserialize, Serialize)]
pub enum HighlightStyle {
Operator, // =+-<>...
Comma,
String,
FunctionName,
Type,
@ -25,6 +26,7 @@ pub fn default_highlight_map() -> HashMap<HighlightStyle, RgbaTup> {
let mut highlight_map = HashMap::new();
[
(Operator, colors::WHITE),
(Comma, from_hsb(258, 50, 90)),
(String, from_hsb(346, 65, 97)),
(FunctionName, colors::WHITE),
(Type, colors::WHITE),

View file

@ -83,7 +83,7 @@ impl Scope {
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) {
Some((symbol, _)) => Ok(*symbol),
None => Err(RuntimeError::LookupNotInScope(

View file

@ -9,9 +9,12 @@ edition = "2018"
[dependencies]
pulldown-cmark = { version = "0.8", default-features = false }
roc_ast = { path = "../ast" }
roc_load = { path = "../compiler/load" }
roc_builtins = { path = "../compiler/builtins" }
roc_can = { path = "../compiler/can" }
roc_code_markup = { path = "../code_markup"}
roc_fmt = { path = "../compiler/fmt" }
roc_module = { path = "../compiler/module" }
roc_region = { path = "../compiler/region" }
roc_types = { path = "../compiler/types" }
@ -22,3 +25,5 @@ bumpalo = { version = "3.2", features = ["collections"] }
[dev-dependencies]
pretty_assertions = "0.5.1"
maplit = "1.0.1"
tempfile = "3.2.0"
uuid = { version = "0.8", features = ["v4"] }

79
docs/src/def.rs Normal file
View file

@ -0,0 +1,79 @@
use bumpalo::{collections::String as BumpString, Bump};
use roc_ast::{
ast_error::ASTResult,
lang::{self, core::def::def_to_def2::def_to_def2},
mem_pool::pool::Pool,
};
use roc_code_markup::{markup::nodes::def2_to_markup, slow_pool::SlowPool};
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds};
use roc_region::all::Region;
use roc_types::subs::VarStore;
use crate::html::mark_node_to_html;
// html is written to buf
pub fn defs_to_html<'a>(
buf: &mut BumpString<'a>,
defs: Vec<roc_parse::ast::Def<'a>>,
env_module_id: ModuleId,
env_module_ids: &'a ModuleIds,
interns: &Interns,
) {
let mut env_pool = Pool::with_capacity(1024);
let env_arena = Bump::new();
let mut var_store = VarStore::default();
let dep_idents = IdentIds::exposed_builtins(8);
let exposed_ident_ids = IdentIds::default();
let def_arena = Bump::new();
let mut env = lang::env::Env::new(
env_module_id,
&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);
for def in defs.iter() {
// TODO remove unwrap
write_def_to_bump_str_html(&def_arena, &mut env, &mut scope, region, def, interns, buf)
.unwrap();
}
}
fn write_def_to_bump_str_html<'a, 'b>(
arena: &'a Bump,
env: &mut lang::env::Env<'a>,
scope: &mut lang::scope::Scope,
region: Region,
def: &'a roc_parse::ast::Def<'a>,
interns: &Interns,
buf: &mut BumpString<'b>,
) -> ASTResult<()> {
let def2 = def_to_def2(arena, env, scope, def, region);
let def2_id = env.pool.add(def2);
let mut mark_node_pool = SlowPool::default();
let def2_markup_id = def2_to_markup(
env,
env.pool.get(def2_id),
def2_id,
&mut mark_node_pool,
interns,
)?;
let def2_markup_node = mark_node_pool.get(def2_markup_id);
mark_node_to_html(def2_markup_node, &mark_node_pool, buf);
Ok(())
}

73
docs/src/expr.rs Normal file
View file

@ -0,0 +1,73 @@
use crate::html::mark_node_to_html;
use bumpalo::{collections::String as BumpString, Bump};
use roc_ast::{
ast_error::ASTResult,
lang::{self, core::expr::expr_to_expr2::expr_to_expr2},
mem_pool::pool::Pool,
};
use roc_code_markup::{markup::nodes::expr2_to_markup, slow_pool::SlowPool};
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds};
use roc_parse::ast::Expr;
use roc_region::all::Region;
use roc_types::subs::VarStore;
// html is written to buf
pub 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 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,
&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();
}
fn write_expr_to_bump_str_html<'a, 'b>(
env: &mut lang::env::Env<'a>,
scope: &mut lang::scope::Scope,
region: Region,
expr: &'a Expr,
interns: &Interns,
buf: &mut BumpString<'b>,
) -> ASTResult<()> {
let (expr2, _) = expr_to_expr2(env, scope, expr, region);
let expr2_id = env.pool.add(expr2);
let mut mark_node_pool = SlowPool::default();
let expr2_markup_id = expr2_to_markup(
env,
env.pool.get(expr2_id),
expr2_id,
&mut mark_node_pool,
interns,
)?;
let expr2_markup_node = mark_node_pool.get(expr2_markup_id);
mark_node_to_html(expr2_markup_node, &mark_node_pool, buf);
Ok(())
}

80
docs/src/html.rs Normal file
View file

@ -0,0 +1,80 @@
use bumpalo::collections::String as BumpString;
use roc_code_markup::{markup::nodes::MarkupNode, slow_pool::SlowPool};
// determine appropriate css class for MarkupNode
pub fn mark_node_to_html<'a>(
mark_node: &MarkupNode,
mark_node_pool: &SlowPool,
buf: &mut BumpString<'a>,
) {
let additional_newlines: usize;
match mark_node {
MarkupNode::Nested {
children_ids,
newlines_at_end,
..
} => {
for &child_id in children_ids {
mark_node_to_html(mark_node_pool.get(child_id), mark_node_pool, buf)
}
additional_newlines = *newlines_at_end;
}
MarkupNode::Text {
content,
syn_high_style,
newlines_at_end,
..
} => {
use roc_code_markup::syntax_highlight::HighlightStyle::*;
let css_class = match syn_high_style {
Operator => "operator",
Comma => "comma",
String => "string",
FunctionName => "function_name",
Type => "type",
Bracket => "bracket",
Number => "number",
PackageRelated => "package-related",
Variable => "variable",
RecordField => "recordfield",
Import => "import",
Provides => "provides",
Blank => "blank",
};
write_html_to_buf(content, css_class, buf);
additional_newlines = *newlines_at_end;
}
MarkupNode::Blank {
newlines_at_end, ..
} => {
let mut content_str = " ".to_string();
for _ in 0..*newlines_at_end {
content_str.push('\n');
}
write_html_to_buf(&content_str, "blank", buf);
additional_newlines = *newlines_at_end;
}
}
for _ in 0..additional_newlines {
buf.push('\n')
}
}
fn write_html_to_buf<'a>(content: &str, css_class: &'static str, buf: &mut BumpString<'a>) {
let opening_tag: String = ["<span class=\"syntax-", css_class, "\">"].concat();
buf.push_str(opening_tag.as_str());
buf.push_str(content);
buf.push_str("</span>");
}

View file

@ -1,6 +1,8 @@
extern crate pulldown_cmark;
extern crate roc_load;
use bumpalo::Bump;
use bumpalo::{collections::String as BumpString, collections::Vec as BumpVec, Bump};
use def::defs_to_html;
use expr::expr_to_html;
use roc_builtins::std::StdLib;
use roc_can::builtins::builtin_defs_map;
use roc_can::scope::Scope;
@ -9,15 +11,19 @@ use roc_load::docs::DocEntry::DocDef;
use roc_load::docs::{DocEntry, TypeAnnotation};
use roc_load::docs::{ModuleDocumentation, RecordField};
use roc_load::file::{LoadedModule, LoadingProblem};
use roc_module::symbol::{IdentIds, Interns, ModuleId};
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds};
use roc_parse::ident::{parse_ident, Ident};
use roc_parse::parser::State;
use roc_parse::parser::{State, SyntaxError};
use roc_region::all::Region;
use std::fs;
use std::path::{Path, PathBuf};
pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
let files_docs = files_to_documentations(filenames, std_lib);
mod def;
mod expr;
mod html;
pub fn generate_docs_html(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
let loaded_modules = load_modules_for_files(filenames, std_lib);
let mut arena = Bump::new();
//
@ -26,7 +32,7 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
name: "roc/builtins".to_string(),
version: "1.0.0".to_string(),
docs: "Package introduction or README.".to_string(),
modules: files_docs,
modules: loaded_modules,
};
if !build_dir.exists() {
@ -53,11 +59,11 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
.expect("TODO gracefully handle failing to make the favicon");
let template_html = include_str!("./static/index.html")
.replace("<!-- search.js -->", &format!("{}search.js", base_href()))
.replace("<!-- styles.css -->", &format!("{}styles.css", base_href()))
.replace("<!-- search.js -->", &format!("{}search.js", base_url()))
.replace("<!-- styles.css -->", &format!("{}styles.css", base_url()))
.replace(
"<!-- favicon.svg -->",
&format!("{}favicon.svg", base_href()),
&format!("{}favicon.svg", base_url()),
)
.replace(
"<!-- Module links -->",
@ -79,8 +85,8 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
for loaded_module in package.modules.iter_mut() {
arena.reset();
let mut exports: bumpalo::collections::Vec<&str> =
bumpalo::collections::Vec::with_capacity_in(loaded_module.exposed_values.len(), &arena);
let mut exports: BumpVec<&str> =
BumpVec::with_capacity_in(loaded_module.exposed_values.len(), &arena);
// TODO should this also include exposed_aliases?
for symbol in loaded_module.exposed_values.iter() {
@ -89,8 +95,8 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
let exports = exports.into_bump_slice();
for module in loaded_module.documentation.values_mut() {
let module_dir = build_dir.join(module.name.replace(".", "/").as_str());
for module_docs in loaded_module.documentation.values() {
let module_dir = build_dir.join(module_docs.name.replace(".", "/").as_str());
fs::create_dir_all(&module_dir)
.expect("TODO gracefully handle not being able to create the module dir");
@ -103,14 +109,7 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
)
.replace(
"<!-- Module Docs -->",
render_main_content(
loaded_module.module_id,
exports,
&loaded_module.dep_idents,
&loaded_module.interns,
module,
)
.as_str(),
render_module_documentation(exports, module_docs, loaded_module).as_str(),
);
fs::write(module_dir.join("index.html"), rendered_module)
@ -121,20 +120,63 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
println!("🎉 Docs generated in {}", build_dir.display());
}
fn render_main_content(
home: ModuleId,
exposed_values: &[&str],
dep_idents: &MutMap<ModuleId, IdentIds>,
// converts plain-text code to highlighted html
pub fn syntax_highlight_expr<'a>(
arena: &'a Bump,
buf: &mut BumpString<'a>,
code_str: &'a str,
env_module_id: ModuleId,
env_module_ids: &'a ModuleIds,
interns: &Interns,
module: &mut ModuleDocumentation,
) -> Result<String, SyntaxError<'a>> {
let trimmed_code_str = code_str.trim_end().trim();
let state = State::new(trimmed_code_str.as_bytes());
match roc_parse::expr::test_parse_expr(0, arena, state) {
Ok(loc_expr) => {
expr_to_html(buf, loc_expr.value, env_module_id, env_module_ids, interns);
Ok(buf.to_string())
}
Err(fail) => Err(SyntaxError::Expr(fail)),
}
}
// converts plain-text code to highlighted html
pub fn syntax_highlight_top_level_defs<'a>(
arena: &'a Bump,
buf: &mut BumpString<'a>,
code_str: &'a str,
env_module_id: ModuleId,
env_module_ids: &'a ModuleIds,
interns: &Interns,
) -> Result<String, SyntaxError<'a>> {
let trimmed_code_str = code_str.trim_end().trim();
match roc_parse::test_helpers::parse_defs_with(arena, trimmed_code_str) {
Ok(vec_loc_def) => {
let vec_def = vec_loc_def.iter().map(|loc| loc.value).collect();
defs_to_html(buf, vec_def, env_module_id, env_module_ids, interns);
Ok(buf.to_string())
}
Err(err) => Err(err),
}
}
fn render_module_documentation(
exposed_values: &[&str],
module: &ModuleDocumentation,
loaded_module: &LoadedModule,
) -> String {
let mut buf = String::new();
buf.push_str(
html_node(
html_to_string(
"h2",
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(),
);
@ -158,7 +200,9 @@ fn render_main_content(
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 {
content.push(' ');
@ -177,7 +221,7 @@ fn render_main_content(
type_annotation_to_html(0, &mut content, type_ann);
buf.push_str(
html_node(
html_to_string(
"h3",
vec![("id", name), ("class", "entry-name")],
content.as_str(),
@ -188,12 +232,10 @@ fn render_main_content(
if let Some(docs) = &doc_def.docs {
buf.push_str(
markdown_to_html(
home,
exposed_values,
dep_idents,
&mut module.scope,
interns,
&module.scope,
docs.to_string(),
loaded_module,
)
.as_str(),
);
@ -201,12 +243,10 @@ fn render_main_content(
}
DocEntry::DetachedDoc(docs) => {
let markdown = markdown_to_html(
home,
exposed_values,
dep_idents,
&mut module.scope,
interns,
&module.scope,
docs.to_string(),
loaded_module,
);
buf.push_str(markdown.as_str());
}
@ -217,7 +257,7 @@ fn render_main_content(
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();
buf.push('<');
@ -246,62 +286,62 @@ fn html_node(tag_name: &str, attrs: Vec<(&str, &str)>, content: &str) -> String
buf
}
fn base_href() -> String {
fn base_url() -> String {
// 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
match std::env::var("ROC_DOCS_URL_ROOT") {
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('/') {
href.push('/');
url_str.push('/');
}
href.push_str(&root_builtins_path);
url_str.push_str(&root_builtins_path);
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 {
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(
html_node(
html_to_string(
"h1",
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(),
);
let mut versions_href = base_href();
let mut versions_url_str = base_url();
versions_href.push('/');
versions_href.push_str(name);
versions_href.push('/');
versions_href.push_str(version);
versions_url_str.push('/');
versions_url_str.push_str(name);
versions_url_str.push('/');
versions_url_str.push_str(version);
buf.push_str(
html_node(
html_to_string(
"a",
vec![("class", "version"), ("href", versions_href.as_str())],
vec![("class", "version"), ("href", versions_url_str.as_str())],
version,
)
.as_str(),
@ -321,13 +361,13 @@ fn render_sidebar<'a, I: Iterator<Item = (Vec<String>, &'a ModuleDocumentation)>
let name = module.name.as_str();
let href = {
let mut href_buf = base_href();
let mut href_buf = base_url();
href_buf.push_str(name);
href_buf
};
sidebar_entry_content.push_str(
html_node(
html_to_string(
"a",
vec![("class", "sidebar-module-link"), ("href", href.as_str())],
name,
@ -348,7 +388,7 @@ fn render_sidebar<'a, I: Iterator<Item = (Vec<String>, &'a ModuleDocumentation)>
entry_href.push_str(doc_def.name.as_str());
entries_buf.push_str(
html_node(
html_to_string(
"a",
vec![("href", entry_href.as_str())],
doc_def.name.as_str(),
@ -363,7 +403,7 @@ fn render_sidebar<'a, I: Iterator<Item = (Vec<String>, &'a ModuleDocumentation)>
};
sidebar_entry_content.push_str(
html_node(
html_to_string(
"div",
vec![("class", "sidebar-sub-entries")],
entries.as_str(),
@ -372,7 +412,7 @@ fn render_sidebar<'a, I: Iterator<Item = (Vec<String>, &'a ModuleDocumentation)>
);
buf.push_str(
html_node(
html_to_string(
"div",
vec![("class", "sidebar-entry")],
sidebar_entry_content.as_str(),
@ -384,9 +424,9 @@ fn render_sidebar<'a, I: Iterator<Item = (Vec<String>, &'a ModuleDocumentation)>
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 mut files_docs = vec![];
let mut modules = vec![];
for filename in filenames {
let mut src_dir = filename.clone();
@ -401,7 +441,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
builtin_defs_map,
) {
Ok(loaded) => files_docs.push(loaded),
Ok(loaded) => modules.push(loaded),
Err(LoadingProblem::FormattedReport(report)) => {
println!("{}", report);
panic!();
@ -410,7 +450,7 @@ pub fn files_to_documentations(filenames: Vec<PathBuf>, std_lib: StdLib) -> Vec<
}
}
files_docs
modules
}
const INDENT: &str = " ";
@ -425,6 +465,7 @@ fn new_line(buf: &mut String) {
buf.push('\n');
}
// html is written to buf
fn type_annotation_to_html(indent_level: usize, buf: &mut String, type_ann: &TypeAnnotation) {
let is_multiline = should_be_multiline(type_ann);
match type_ann {
@ -686,7 +727,7 @@ fn doc_url<'a>(
home: ModuleId,
exposed_values: &[&str],
dep_idents: &MutMap<ModuleId, IdentIds>,
scope: &mut Scope,
scope: &Scope,
interns: &'a Interns,
mut module_name: &'a str,
ident: &str,
@ -753,7 +794,7 @@ fn doc_url<'a>(
}
}
let mut url = base_href();
let mut url = base_url();
// Example:
//
@ -769,12 +810,10 @@ fn doc_url<'a>(
}
fn markdown_to_html(
home: ModuleId,
exposed_values: &[&str],
dep_idents: &MutMap<ModuleId, IdentIds>,
scope: &mut Scope,
interns: &Interns,
scope: &Scope,
markdown: String,
loaded_module: &LoadedModule,
) -> String {
use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Tag::*};
@ -801,11 +840,11 @@ fn markdown_to_html(
match iter.next() {
Some(symbol_name) if iter.next().is_none() => {
let DocUrl { url, title } = doc_url(
home,
loaded_module.module_id,
exposed_values,
dep_idents,
&loaded_module.dep_idents,
scope,
interns,
&loaded_module.interns,
module_name,
symbol_name,
);
@ -824,11 +863,11 @@ fn markdown_to_html(
// This looks like a global tag name, but it could
// be a type alias that's in scope, e.g. [I64]
let DocUrl { url, title } = doc_url(
home,
loaded_module.module_id,
exposed_values,
dep_idents,
&loaded_module.dep_idents,
scope,
interns,
&loaded_module.interns,
"",
type_name,
);
@ -843,6 +882,9 @@ fn markdown_to_html(
};
let markdown_options = pulldown_cmark::Options::empty();
let mut expecting_code_block = false;
let mut docs_parser = vec![];
let (_, _) = pulldown_cmark::Parser::new_with_broken_link_callback(
&markdown,
@ -850,6 +892,7 @@ fn markdown_to_html(
Some(&mut broken_link_callback),
)
.fold((0, 0), |(start_quote_count, end_quote_count), event| {
match &event {
// Replace this sequence (`>>>` syntax):
// Start(BlockQuote)
@ -915,6 +958,39 @@ fn markdown_to_html(
(start_quote_count, end_quote_count)
}
Event::Start(CodeBlock(CodeBlockKind::Fenced(_))) => {
expecting_code_block = true;
docs_parser.push(event);
(0, 0)
}
Event::End(CodeBlock(_)) => {
expecting_code_block = false;
docs_parser.push(event);
(0, 0)
}
Event::Text(CowStr::Borrowed(code_str)) if expecting_code_block => {
let code_block_arena = Bump::new();
let mut code_block_buf = BumpString::new_in(&code_block_arena);
match syntax_highlight_expr(
&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) => {
docs_parser.push(Event::Html(CowStr::from(highlighted_code_str)));
}
Err(syntax_error) => {
panic!("Unexpected parse failure when parsing this for rendering in docs:\n\n{}\n\nParse error was:\n\n{:?}\n\n", code_str, syntax_error)
}
};
(0, 0)
}
_ => {
docs_parser.push(event);
(0, 0)

View file

@ -41,7 +41,7 @@
</main>
<footer>
<p>Made by people who like to make nice things.</p>
<p>© 2020</p>
<p>© 2021</p>
</footer>
</body>

View file

@ -7,7 +7,6 @@
--body-bg-color: #fdfdfd;
--border-color: #e9e9e9;
--faded-color: #4c4c4c;
--monospace-font;
--font-sans: -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
--font-mono: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;
--top-header-height: 67px;
@ -283,7 +282,6 @@ code {
font-family: var(--font-mono);
color: var(--code-color);
background-color: var(--code-bg-color);
padding: 2px 8px;
display: inline-block;
}
@ -306,15 +304,34 @@ pre {
overflow-x: auto;
}
pre code {
padding: 6px 8px;
}
.hidden {
/* Use !important to win all specificity fights. */
display: none !important;
}
.syntax-number {
color: #60B7BF;
}
.syntax-string {
color:#F7577C;
}
.syntax-bracket {
color:#FF335F;
}
.syntax-closure-dash,
.syntax-closure-arrow,
.syntax-operator
{
color: #ffffff;
}
.syntax-comma {
color: #9573E6;
}
.syntax-comment {
color: #ff0000;
}
#module-search:placeholder-shown {
padding: 0;
opacity: 0;

View file

@ -0,0 +1,158 @@
#[macro_use]
extern crate pretty_assertions;
#[cfg(test)]
mod insert_doc_syntax_highlighting {
use std::{fs::File, io::Write, path::PathBuf};
use bumpalo::{collections::String as BumpString, Bump};
use roc_ast::module::load_module;
use roc_docs::{syntax_highlight_expr, syntax_highlight_top_level_defs};
use roc_load::file::LoadedModule;
use tempfile::tempdir;
use uuid::Uuid;
fn expect_html(code_str: &str, want: &str, use_expr: bool) {
let loaded_module = make_mock_module();
let code_block_arena = Bump::new();
let mut code_block_buf = BumpString::new_in(&code_block_arena);
if use_expr {
match syntax_highlight_expr(
&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) => {
assert_eq!(highlighted_code_str, want);
}
Err(syntax_error) => {
panic!("Unexpected parse failure when parsing this for rendering in docs:\n\n{}\n\nParse error was:\n\n{:?}\n\n", code_str, syntax_error)
}
};
} else {
match syntax_highlight_top_level_defs(
&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) => {
assert_eq!(highlighted_code_str, want);
}
Err(syntax_error) => {
panic!("Unexpected parse failure when parsing this for rendering in docs:\n\n{}\n\nParse error was:\n\n{:?}\n\n", code_str, syntax_error)
}
};
}
}
pub const HELLO_WORLD: &str = r#"
app "test-app"
packages { base: "platform" }
imports []
provides [ main ] to base
main = "Hello, world!"
"#;
fn make_mock_module() -> LoadedModule {
let temp_dir = tempdir().expect("Failed to create temporary directory for test.");
let temp_file_path_buf =
PathBuf::from([Uuid::new_v4().to_string(), ".roc".to_string()].join(""));
let temp_file_full_path = temp_dir.path().join(temp_file_path_buf);
let mut file = File::create(temp_file_full_path.clone()).expect(&format!(
"Failed to create temporary file for path {:?}",
temp_file_full_path
));
writeln!(file, "{}", HELLO_WORLD).expect(&format!(
"Failed to write {:?} to file: {:?}",
HELLO_WORLD, file
));
load_module(&temp_file_full_path)
}
fn expect_html_expr(code_str: &str, want: &str) {
expect_html(code_str, want, true)
}
fn expect_html_def(code_str: &str, want: &str) {
expect_html(code_str, want, false)
}
#[test]
fn number_expr() {
expect_html_expr("2", r#"<span class="syntax-number">2</span>"#);
}
#[test]
fn string_expr() {
expect_html_expr(r#""abc""#, r#"<span class="syntax-string">"abc"</span>"#);
}
#[test]
fn empty_list_expr() {
expect_html_expr(
r#"[]"#,
r#"<span class="syntax-bracket">[ </span><span class="syntax-bracket"> ]</span>"#,
);
}
#[test]
fn single_elt_list_expr() {
expect_html_expr(
r#"[ 0 ]"#,
r#"<span class="syntax-bracket">[ </span><span class="syntax-number">0</span><span class="syntax-bracket"> ]</span>"#,
);
}
#[test]
fn multi_elt_list_expr() {
expect_html_expr(
r#"[ "hello", "WoRlD" ]"#,
r#"<span class="syntax-bracket">[ </span><span class="syntax-string">"hello"</span><span class="syntax-comma">, </span><span class="syntax-string">"WoRlD"</span><span class="syntax-bracket"> ]</span>"#,
);
}
#[test]
fn record_expr() {
expect_html_expr(
r#"{ a: "hello!" }"#,
"<span class=\"syntax-bracket\">{ </span><span class=\"syntax-recordfield\">a</span><span class=\"syntax-operator\">: </span><span class=\"syntax-string\">\"hello!\"</span><span class=\"syntax-bracket\"> }</span>",
);
}
#[test]
fn nested_record_expr() {
expect_html_expr(
r#"{ a: { bB: "WoRlD" } }"#,
"<span class=\"syntax-bracket\">{ </span><span class=\"syntax-recordfield\">a</span><span class=\"syntax-operator\">: </span><span class=\"syntax-bracket\">{ </span><span class=\"syntax-recordfield\">bB</span><span class=\"syntax-operator\">: </span><span class=\"syntax-string\">\"WoRlD\"</span><span class=\"syntax-bracket\"> }</span><span class=\"syntax-bracket\"> }</span>",
);
}
#[test]
fn top_level_def_value() {
expect_html_def(
r#"main = "Hello, World!""#,
"<span class=\"syntax-variable\">main</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-string\">\"Hello, World!\"</span>\n\n",
);
}
#[test]
fn tld_list() {
expect_html_def(
r#"main = [ 1, 2, 3 ]"#,
"<span class=\"syntax-variable\">main</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-bracket\">[ </span><span class=\"syntax-number\">1</span><span class=\"syntax-comma\">, </span><span class=\"syntax-number\">2</span><span class=\"syntax-comma\">, </span><span class=\"syntax-number\">3</span><span class=\"syntax-bracket\"> ]</span>\n\n",
);
}
}

View file

@ -25,10 +25,7 @@ use fs_extra::dir::{copy, ls, CopyOptions, DirEntryAttr, DirEntryValue};
use pipelines::RectResources;
use roc_ast::lang::env::Env;
use roc_ast::mem_pool::pool::Pool;
use roc_can::builtins::builtin_defs_map;
use roc_collections::all::MutMap;
use roc_load;
use roc_load::file::LoadedModule;
use roc_ast::module::load_module;
use roc_module::symbol::IdentIds;
use roc_types::subs::VarStore;
use std::collections::HashSet;
@ -557,40 +554,6 @@ fn copy_roc_platform_if_not_exists(
}
}
pub fn load_module(src_file: &Path) -> LoadedModule {
let subs_by_module = MutMap::default();
let arena = Bump::new();
let loaded = roc_load::file::load_and_typecheck(
&arena,
src_file.to_path_buf(),
arena.alloc(roc_builtins::std::standard_stdlib()),
src_file.parent().unwrap_or_else(|| {
panic!(
"src_file {:?} did not have a parent directory but I need to have one.",
src_file
)
}),
subs_by_module,
8,
builtin_defs_map,
);
match loaded {
Ok(x) => x,
Err(roc_load::file::LoadingProblem::FormattedReport(report)) => {
panic!(
"Failed to load module from src_file {:?}. Report: {:?}",
src_file, report
);
}
Err(e) => panic!(
"Failed to load module from src_file {:?}: {:?}",
src_file, e
),
}
}
fn queue_no_file_text(
size: &PhysicalSize<u32>,
text: &str,

View file

@ -63,7 +63,6 @@ pub fn init_model<'a>(
EmptyCodeString {}.fail()
} else {
Ok(ast_to_mark_nodes(
code_arena,
&mut module.env,
&module.ast,
&mut mark_node_pool,
@ -199,7 +198,6 @@ impl<'a> EdModule<'a> {
#[cfg(test)]
pub mod test_ed_model {
use crate::editor::ed_error::EdResult;
use crate::editor::main::load_module;
use crate::editor::mvc::ed_model;
use crate::editor::resources::strings::HELLO_WORLD;
use crate::ui::text::caret_w_select::test_caret_w_select::convert_dsl_to_selection;
@ -212,6 +210,7 @@ pub mod test_ed_model {
use ed_model::EdModel;
use roc_ast::lang::env::Env;
use roc_ast::mem_pool::pool::Pool;
use roc_ast::module::load_module;
use roc_load::file::LoadedModule;
use roc_module::symbol::IdentIds;
use roc_module::symbol::ModuleIds;

View file

@ -282,7 +282,6 @@ code {
font-family: var(--font-mono);
color: var(--code-color);
background-color: var(--code-bg-color);
padding: 0 8px;
display: inline-block;
line-height: 28px;
}
@ -303,15 +302,15 @@ pre {
overflow-x: auto;
}
pre code {
padding: 6px 8px;
}
.hidden {
/* Use !important to win all specificity fights. */
display: none !important;
}
.syntax-comment {
color: #ff0000;
}
#module-search:placeholder-shown {
padding: 0;
opacity: 0;