From e5d3185abfce8be66371ab4a73810153fe65e114 Mon Sep 17 00:00:00 2001 From: Chris-san <57543709+eureka-cpu@users.noreply.github.com> Date: Mon, 22 May 2023 13:27:32 -0500 Subject: [PATCH] `forc doc`: Generate dependency documentation (#4546) ## Description Generates the documentation for dependencies & small improvements to the API. These changes **DO NOT** create links between dependency docs and the main docs, but generates the dependency docs and ensures there are no conflicts when generating these docs. What's new so far: - [x] Programs get their own folders, just like `cargo doc` - [x] Generates documentation for dependencies by default: Closes #4533 - [x] Fixes possible conflict with `assets` folder: Closes #4545 - [x] Removes old docs before generating new ones: Closes #4544 ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [x] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [ ] I have added tests that prove my fix is effective or that my feature works. - [x] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers. --------- Co-authored-by: Chris O'Brien --- Cargo.lock | 1 + forc-plugins/forc-doc/Cargo.toml | 1 + forc-plugins/forc-doc/src/doc/mod.rs | 190 ++++++++-------- forc-plugins/forc-doc/src/doc/module.rs | 2 +- forc-plugins/forc-doc/src/licenses/README.md | 2 +- forc-plugins/forc-doc/src/main.rs | 212 +++++++++++++----- forc-plugins/forc-doc/src/render/index.rs | 26 +-- .../forc-doc/src/render/item/components.rs | 19 +- forc-plugins/forc-doc/src/render/mod.rs | 4 +- forc-plugins/forc-doc/src/render/sidebar.rs | 17 +- .../FiraSans-Medium.woff2 | Bin .../FiraSans-Regular.woff2 | Bin .../NanumBarunGothic.ttf.woff2 | Bin .../SourceCodePro-It.ttf.woff2 | Bin .../SourceCodePro-Regular.ttf.woff2 | Bin .../SourceCodePro-Semibold.ttf.woff2 | Bin .../SourceSerif4-Bold.ttf.woff2 | Bin .../SourceSerif4-It.ttf.woff2 | Bin .../SourceSerif4-Regular.ttf.woff2 | Bin .../src/{assets => static.files}/ayu.css | 0 .../src/{assets => static.files}/ayu.min.css | 0 .../{assets => static.files}/clipboard.svg | 0 .../{assets => static.files}/down-arrow.svg | 0 .../src/{assets => static.files}/highlight.js | 0 .../{assets => static.files}/normalize.css | 0 .../{assets => static.files}/sway-logo.svg | 0 .../src/{assets => static.files}/swaydoc.css | 0 .../{assets => static.files}/toggle-minus.svg | 0 .../{assets => static.files}/toggle-plus.svg | 0 .../src/{assets => static.files}/wheel.svg | 0 scripts/highlightjs/build.sh | 2 +- 31 files changed, 295 insertions(+), 181 deletions(-) rename forc-plugins/forc-doc/src/{assets => static.files}/FiraSans-Medium.woff2 (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/FiraSans-Regular.woff2 (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/NanumBarunGothic.ttf.woff2 (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/SourceCodePro-It.ttf.woff2 (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/SourceCodePro-Regular.ttf.woff2 (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/SourceCodePro-Semibold.ttf.woff2 (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/SourceSerif4-Bold.ttf.woff2 (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/SourceSerif4-It.ttf.woff2 (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/SourceSerif4-Regular.ttf.woff2 (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/ayu.css (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/ayu.min.css (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/clipboard.svg (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/down-arrow.svg (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/highlight.js (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/normalize.css (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/sway-logo.svg (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/swaydoc.css (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/toggle-minus.svg (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/toggle-plus.svg (100%) rename forc-plugins/forc-doc/src/{assets => static.files}/wheel.svg (100%) diff --git a/Cargo.lock b/Cargo.lock index 27dfbc7d08c..ed46bc49e24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1734,6 +1734,7 @@ version = "0.39.0" dependencies = [ "anyhow", "clap 4.2.7", + "colored", "comrak", "forc-pkg", "forc-util", diff --git a/forc-plugins/forc-doc/Cargo.toml b/forc-plugins/forc-doc/Cargo.toml index 21e3941db14..603f8e04152 100644 --- a/forc-plugins/forc-doc/Cargo.toml +++ b/forc-plugins/forc-doc/Cargo.toml @@ -11,6 +11,7 @@ repository.workspace = true [dependencies] anyhow = "1.0.65" clap = { version = "4.0.18", features = ["derive"] } +colored = "2.0.0" comrak = "0.16" forc-pkg = { version = "0.39.0", path = "../../forc-pkg" } forc-util = { version = "0.39.0", path = "../../forc-util" } diff --git a/forc-plugins/forc-doc/src/doc/mod.rs b/forc-plugins/forc-doc/src/doc/mod.rs index 0acb8dc36d6..d5fe21cc475 100644 --- a/forc-plugins/forc-doc/src/doc/mod.rs +++ b/forc-plugins/forc-doc/src/doc/mod.rs @@ -6,107 +6,57 @@ use anyhow::Result; use std::option::Option; use sway_core::{ decl_engine::DeclEngine, - language::ty::{TyAstNodeContent, TyDecl, TyImplTrait, TyProgram, TySubmodule}, + language::ty::{TyAstNodeContent, TyDecl, TyImplTrait, TyModule, TyProgram, TySubmodule}, }; use sway_types::Spanned; mod descriptor; pub mod module; -pub(crate) type Documentation = Vec; -/// A finalized Document ready to be rendered. We want to retain all -/// information including spans, fields on structs, variants on enums etc. -#[derive(Clone, Debug)] -pub(crate) struct Document { - pub(crate) module_info: ModuleInfo, - pub(crate) item_header: ItemHeader, - pub(crate) item_body: ItemBody, - pub(crate) raw_attributes: Option, -} -impl Document { - /// Creates an HTML file name from the [Document]. - pub(crate) fn html_filename(&self) -> String { - use sway_core::language::ty::TyDecl::StorageDecl; - let name = match &self.item_body.ty_decl { - StorageDecl { .. } => None, - _ => Some(self.item_header.item_name.as_str()), - }; - - Document::create_html_filename(self.item_body.ty_decl.doc_name(), name) - } - fn create_html_filename(ty: &str, name: Option<&str>) -> String { - match name { - Some(name) => format!("{ty}.{name}.html"), - None => { - format!("{ty}.html") // storage does not have an Ident - } - } - } - /// Generate link info used in navigation between docs. - pub(crate) fn link(&self) -> DocLink { - DocLink { - name: self.item_header.item_name.as_str().to_owned(), - module_info: self.module_info.clone(), - html_filename: self.html_filename(), - preview_opt: self.preview_opt(), - } - } - fn preview_opt(&self) -> Option { - create_preview(self.raw_attributes.clone()) - } +#[derive(Default)] +pub(crate) struct Documentation(pub(crate) Vec); +impl Documentation { /// Gather [Documentation] from the [TyProgram]. pub(crate) fn from_ty_program( decl_engine: &DeclEngine, project_name: &str, typed_program: &TyProgram, - no_deps: bool, document_private_items: bool, ) -> Result { // the first module prefix will always be the project name let mut docs: Documentation = Default::default(); let mut impl_traits: Vec = Vec::new(); - for ast_node in &typed_program.root.all_nodes { - if let TyAstNodeContent::Declaration(ref decl) = ast_node.content { - if let TyDecl::ImplTrait(impl_trait) = decl { - impl_traits.push(decl_engine.get_impl_trait(&impl_trait.decl_id)) - } else { - let desc = Descriptor::from_typed_decl( - decl_engine, - decl, - ModuleInfo::from_ty_module(vec![project_name.to_owned()], None), - document_private_items, - )?; - - if let Descriptor::Documentable(doc) = desc { - docs.push(doc) - } - } - } - } + let module_info = ModuleInfo::from_ty_module(vec![project_name.to_owned()], None); + Documentation::from_ty_module( + decl_engine, + module_info, + &typed_program.root, + &mut docs, + &mut impl_traits, + document_private_items, + )?; - if !no_deps && !typed_program.root.submodules.is_empty() { - // this is the same process as before but for dependencies - for (_, ref typed_submodule) in &typed_program.root.submodules { - let attributes = (!typed_submodule.module.attributes.is_empty()) - .then(|| typed_submodule.module.attributes.to_html_string()); - let module_prefix = - ModuleInfo::from_ty_module(vec![project_name.to_owned()], attributes); - Document::from_ty_submodule( - decl_engine, - typed_submodule, - &mut docs, - &mut impl_traits, - &module_prefix, - document_private_items, - )?; - } + // this is the same process as before but for submodules + for (_, ref typed_submodule) in &typed_program.root.submodules { + let attributes = (!typed_submodule.module.attributes.is_empty()) + .then(|| typed_submodule.module.attributes.to_html_string()); + let module_prefix = + ModuleInfo::from_ty_module(vec![project_name.to_owned()], attributes); + Documentation::from_ty_submodule( + decl_engine, + typed_submodule, + &mut docs, + &mut impl_traits, + &module_prefix, + document_private_items, + )?; } // match for the spans to add the impl_traits to their corresponding doc: // currently this compares the spans as str, but this needs to change // to compare the actual types if !impl_traits.is_empty() { - for doc in &mut docs { + for doc in &mut docs.0 { let mut impl_vec: Vec = Vec::new(); match doc.item_body.ty_decl { @@ -132,19 +82,15 @@ impl Document { Ok(docs) } - fn from_ty_submodule( + fn from_ty_module( decl_engine: &DeclEngine, - typed_submodule: &TySubmodule, + module_info: ModuleInfo, + ty_module: &TyModule, docs: &mut Documentation, impl_traits: &mut Vec, - module_prefix: &ModuleInfo, document_private_items: bool, ) -> Result<()> { - let mut new_submodule_prefix = module_prefix.to_owned(); - new_submodule_prefix - .module_prefixes - .push(typed_submodule.mod_name_span.as_str().to_owned()); - for ast_node in &typed_submodule.module.all_nodes { + for ast_node in &ty_module.all_nodes { if let TyAstNodeContent::Declaration(ref decl) = ast_node.content { if let TyDecl::ImplTrait(impl_trait) = decl { impl_traits.push(decl_engine.get_impl_trait(&impl_trait.decl_id)) @@ -152,24 +98,47 @@ impl Document { let desc = Descriptor::from_typed_decl( decl_engine, decl, - new_submodule_prefix.clone(), + module_info.clone(), document_private_items, )?; if let Descriptor::Documentable(doc) = desc { - docs.push(doc) + docs.0.push(doc) } } } } + Ok(()) + } + fn from_ty_submodule( + decl_engine: &DeclEngine, + typed_submodule: &TySubmodule, + docs: &mut Documentation, + impl_traits: &mut Vec, + module_info: &ModuleInfo, + document_private_items: bool, + ) -> Result<()> { + let mut module_info = module_info.to_owned(); + module_info + .module_prefixes + .push(typed_submodule.mod_name_span.as_str().to_owned()); + Documentation::from_ty_module( + decl_engine, + module_info.clone(), + &typed_submodule.module, + docs, + impl_traits, + document_private_items, + )?; + for (_, submodule) in &typed_submodule.module.submodules { - Document::from_ty_submodule( + Documentation::from_ty_submodule( decl_engine, submodule, docs, impl_traits, - &new_submodule_prefix, + &module_info, document_private_items, )?; } @@ -177,3 +146,44 @@ impl Document { Ok(()) } } +/// A finalized Document ready to be rendered. We want to retain all +/// information including spans, fields on structs, variants on enums etc. +#[derive(Clone, Debug)] +pub(crate) struct Document { + pub(crate) module_info: ModuleInfo, + pub(crate) item_header: ItemHeader, + pub(crate) item_body: ItemBody, + pub(crate) raw_attributes: Option, +} +impl Document { + /// Creates an HTML file name from the [Document]. + pub(crate) fn html_filename(&self) -> String { + use sway_core::language::ty::TyDecl::StorageDecl; + let name = match &self.item_body.ty_decl { + StorageDecl { .. } => None, + _ => Some(self.item_header.item_name.as_str()), + }; + + Document::create_html_filename(self.item_body.ty_decl.doc_name(), name) + } + fn create_html_filename(ty: &str, name: Option<&str>) -> String { + match name { + Some(name) => format!("{ty}.{name}.html"), + None => { + format!("{ty}.html") // storage does not have an Ident + } + } + } + /// Generate link info used in navigation between docs. + pub(crate) fn link(&self) -> DocLink { + DocLink { + name: self.item_header.item_name.as_str().to_owned(), + module_info: self.module_info.clone(), + html_filename: self.html_filename(), + preview_opt: self.preview_opt(), + } + } + fn preview_opt(&self) -> Option { + create_preview(self.raw_attributes.clone()) + } +} diff --git a/forc-plugins/forc-doc/src/doc/module.rs b/forc-plugins/forc-doc/src/doc/module.rs index d249115d3fa..e32585d5e11 100644 --- a/forc-plugins/forc-doc/src/doc/module.rs +++ b/forc-plugins/forc-doc/src/doc/module.rs @@ -157,7 +157,7 @@ impl ModuleInfo { } /// Create a path prefix `&str` for navigation from the `module.depth()`. fn to_html_path_prefix(&self) -> String { - (1..self.depth()).map(|_| "../").collect::() + (0..self.depth()).map(|_| "../").collect::() } /// The depth of a module as `usize`. pub(crate) fn depth(&self) -> usize { diff --git a/forc-plugins/forc-doc/src/licenses/README.md b/forc-plugins/forc-doc/src/licenses/README.md index b58d73e60bd..df27ace58ac 100644 --- a/forc-plugins/forc-doc/src/licenses/README.md +++ b/forc-plugins/forc-doc/src/licenses/README.md @@ -1,3 +1,3 @@ # Assets Licenses Notice -This `licenses` directory contains all of the licenses associated with the assets contained within the [`assets`](../assets/) directory. +This `licenses` directory contains all of the licenses associated with the assets contained within the [`static.files`](../static.files/) directory. diff --git a/forc-plugins/forc-doc/src/main.rs b/forc-plugins/forc-doc/src/main.rs index a67b40570e2..82b34084431 100644 --- a/forc-plugins/forc-doc/src/main.rs +++ b/forc-plugins/forc-doc/src/main.rs @@ -1,15 +1,21 @@ use crate::{ - doc::{Document, Documentation}, + doc::Documentation, render::{constant::INDEX_FILENAME, RenderedDocumentation}, }; use anyhow::{bail, Result}; use clap::Parser; use cli::Command; +use colored::*; use forc_pkg as pkg; use forc_util::default_output_directory; use include_dir::{include_dir, Dir}; -use pkg::manifest::ManifestFile; +use pkg::{ + manifest::{Dependency, ManifestFile}, + PackageManifestFile, +}; use std::{ + collections::BTreeMap, + path::Path, process::Command as Process, sync::Arc, {fs, path::PathBuf}, @@ -20,6 +26,8 @@ mod cli; mod doc; mod render; +pub(crate) const ASSETS_DIR_NAME: &str = "static.files"; + /// Information passed to the render phase to get TypeInfo, CallPath or visibility for type anchors. #[derive(Clone)] struct RenderPlan { @@ -43,18 +51,10 @@ impl RenderPlan { /// Main method for `forc doc`. pub fn main() -> Result<()> { - let Command { - manifest_path, - document_private_items, - open: open_result, - offline, - silent, - locked, - no_deps, - } = Command::parse(); + let build_instructions = Command::parse(); // get manifest directory - let dir = if let Some(ref path) = manifest_path { + let dir = if let Some(ref path) = build_instructions.manifest_path { PathBuf::from(path) } else { std::env::current_dir()? @@ -68,11 +68,81 @@ pub fn main() -> Result<()> { // create doc path const DOC_DIR_NAME: &str = "doc"; - let project_name = &pkg_manifest.project.name; let out_path = default_output_directory(manifest.dir()); let doc_path = out_path.join(DOC_DIR_NAME); + if doc_path.exists() { + std::fs::remove_dir_all(&doc_path)?; + } fs::create_dir_all(&doc_path)?; + // build core documentation + build_docs(&manifest, pkg_manifest, &doc_path, &build_instructions)?; + + // CSS, icons and logos + static ASSETS_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/src/static.files"); + let assets_path = doc_path.join(ASSETS_DIR_NAME); + fs::create_dir_all(&assets_path)?; + for file in ASSETS_DIR.files() { + let asset_path = assets_path.join(file.path()); + fs::write(asset_path, file.contents())?; + } + // Sway syntax highlighting file + const SWAY_HJS_FILENAME: &str = "highlight.js"; + let sway_hjs = std::include_bytes!("static.files/highlight.js"); + fs::write(assets_path.join(SWAY_HJS_FILENAME), sway_hjs)?; + + // check if the user wants to open the doc in the browser + // if opening in the browser fails, attempt to open using a file explorer + if build_instructions.open { + const BROWSER_ENV_VAR: &str = "BROWSER"; + let path = doc_path + .join(pkg_manifest.project_name()) + .join(INDEX_FILENAME); + let default_browser_opt = std::env::var_os(BROWSER_ENV_VAR); + match default_browser_opt { + Some(def_browser) => { + let browser = PathBuf::from(def_browser); + if let Err(e) = Process::new(&browser).arg(path).status() { + bail!( + "Couldn't open docs with {}: {}", + browser.to_string_lossy(), + e + ); + } + } + None => { + if let Err(e) = opener::open(&path) { + bail!("Couldn't open docs: {}", e); + } + } + } + } + + Ok(()) +} + +fn build_docs( + manifest: &ManifestFile, + pkg_manifest: &PackageManifestFile, + doc_path: &Path, + build_instructions: &Command, +) -> Result<()> { + let Command { + document_private_items, + offline, + silent, + locked, + no_deps, + .. + } = *build_instructions; + + println!( + " {} {} ({})", + "Compiling".bold().yellow(), + pkg_manifest.project_name(), + manifest.dir().to_string_lossy() + ); + // compile the program and extract the docs let member_manifests = manifest.member_manifests()?; let lock_path = manifest.lock_path()?; @@ -97,22 +167,28 @@ pub fn main() -> Result<()> { Some(typed_program) => typed_program, _ => bail!("CompileResult returned None"), }; - let raw_docs: Documentation = Document::from_ty_program( + + println!( + " {} documentation for {} ({})", + "Building".bold().yellow(), + pkg_manifest.project_name(), + manifest.dir().to_string_lossy() + ); + + let raw_docs = Documentation::from_ty_program( &decl_engine, - project_name, + pkg_manifest.project_name(), &typed_program, - no_deps, document_private_items, )?; let root_attributes = (!typed_program.root.attributes.is_empty()).then_some(typed_program.root.attributes); - let program_kind = typed_program.kind; - // render docs to HTML let forc_version = pkg_manifest .project .forc_version .as_ref() .map(|ver| format!("Forc v{}.{}.{}", ver.major, ver.minor, ver.patch)); + // render docs to HTML let rendered_docs = RenderedDocumentation::from_raw_docs( raw_docs, RenderPlan::new( @@ -121,61 +197,73 @@ pub fn main() -> Result<()> { Arc::from(decl_engine), ), root_attributes, - program_kind, + typed_program.kind, forc_version, )?; - // write contents to outfile + // write file contents to doc folder + write_content(rendered_docs, doc_path)?; + println!(" {}", "Finished".bold().yellow()); + + if !no_deps { + build_deps( + &pkg_manifest.dependencies, + manifest.dir(), + doc_path, + build_instructions, + )?; + } + + Ok(()) +} + +fn build_deps( + dependencies: &Option>, + manifest_dir: &Path, + doc_path: &Path, + build_instructions: &Command, +) -> Result<()> { + if let Some(deps) = dependencies { + for (dep_name, dep) in deps { + if let Dependency::Detailed(dep_details) = dep { + if let Some(path) = &dep_details.path { + let manifest_path = manifest_dir.join(path).canonicalize()?; + let dep_manifest = ManifestFile::from_dir(&manifest_path)?; + let dep_pkg_manifest = + if let ManifestFile::Package(pkg_manifest) = &dep_manifest { + pkg_manifest + } else { + bail!("forc-doc does not support workspaces.") + }; + build_docs( + &dep_manifest, + dep_pkg_manifest, + doc_path, + build_instructions, + )?; + } else { + println!("a path variable was not set for {dep_name}, which is currently the only supported option.") + } + } else { + println!("{dep_name} is a simple format dependency,\nsimple format dependencies don't specify a path to a manfiest file and are unsupported at this time.") + } + } + } + + Ok(()) +} + +fn write_content(rendered_docs: RenderedDocumentation, doc_path: &Path) -> Result<()> { for doc in rendered_docs.0 { - let mut doc_path = doc_path.clone(); + let mut doc_path = doc_path.to_path_buf(); for prefix in doc.module_info.module_prefixes { - if &prefix != project_name { - doc_path.push(prefix); - } + doc_path.push(prefix) } fs::create_dir_all(&doc_path)?; doc_path.push(doc.html_filename); fs::write(&doc_path, doc.file_contents.0.as_bytes())?; } - // CSS, icons and logos - static ASSETS_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/src/assets"); - const ASSETS_DIR_NAME: &str = "assets"; - let assets_path = doc_path.join(ASSETS_DIR_NAME); - fs::create_dir_all(&assets_path)?; - for file in ASSETS_DIR.files() { - let asset_path = assets_path.join(file.path()); - fs::write(asset_path, file.contents())?; - } - // Sway syntax highlighting file - const SWAY_HJS_FILENAME: &str = "highlight.js"; - let sway_hjs = std::include_bytes!("assets/highlight.js"); - fs::write(assets_path.join(SWAY_HJS_FILENAME), sway_hjs)?; - - // check if the user wants to open the doc in the browser - // if opening in the browser fails, attempt to open using a file explorer - if open_result { - const BROWSER_ENV_VAR: &str = "BROWSER"; - let path = doc_path.join(INDEX_FILENAME); - let default_browser_opt = std::env::var_os(BROWSER_ENV_VAR); - match default_browser_opt { - Some(def_browser) => { - let browser = PathBuf::from(def_browser); - if let Err(e) = Process::new(&browser).arg(path).status() { - bail!( - "Couldn't open docs with {}: {}", - browser.to_string_lossy(), - e - ); - } - } - None => { - if let Err(e) = opener::open(&path) { - bail!("Couldn't open docs: {}", e); - } - } - } - } Ok(()) } diff --git a/forc-plugins/forc-doc/src/render/index.rs b/forc-plugins/forc-doc/src/render/index.rs index 02d80db23a3..0eb34f43d63 100644 --- a/forc-plugins/forc-doc/src/render/index.rs +++ b/forc-plugins/forc-doc/src/render/index.rs @@ -1,7 +1,7 @@ use crate::{ doc::module::ModuleInfo, render::{constant::IDENTITY, link::DocLinks, sidebar::*, BlockTitle, DocStyle, Renderable}, - RenderPlan, + RenderPlan, ASSETS_DIR_NAME, }; use anyhow::Result; use horrorshow::{box_html, Raw, RenderBox}; @@ -46,12 +46,12 @@ impl Renderable for AllDocIndex { content="List of all items in this project" ); meta(name="keywords", content="sway, swaylang, sway-lang"); - link(rel="icon", href="assets/sway-logo.svg"); + link(rel="icon", href=format!("../{ASSETS_DIR_NAME}/sway-logo.svg")); title: "List of all items in this project"; - link(rel="stylesheet", type="text/css", href="assets/normalize.css"); - link(rel="stylesheet", type="text/css", href="assets/swaydoc.css", id="mainThemeStyle"); - link(rel="stylesheet", type="text/css", href="assets/ayu.css"); - link(rel="stylesheet", href="assets/ayu.min.css"); + link(rel="stylesheet", type="text/css", href=format!("../{ASSETS_DIR_NAME}/normalize.css")); + link(rel="stylesheet", type="text/css", href=format!("../{ASSETS_DIR_NAME}/swaydoc.css"), id="mainThemeStyle"); + link(rel="stylesheet", type="text/css", href=format!("../{ASSETS_DIR_NAME}/ayu.css")); + link(rel="stylesheet", href=format!("../{ASSETS_DIR_NAME}/ayu.min.css")); } body(class="swaydoc mod") { : sidebar; @@ -86,7 +86,7 @@ impl Renderable for AllDocIndex { } } } - script(src="assets/highlight.js"); + script(src=format!("../{ASSETS_DIR_NAME}/highlight.js")); script { : "hljs.highlightAll();"; } @@ -141,22 +141,22 @@ impl Renderable for ModuleIndex { let favicon = self .module_info - .to_html_shorthand_path_string("assets/sway-logo.svg"); + .to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/sway-logo.svg")); let normalize = self .module_info - .to_html_shorthand_path_string("assets/normalize.css"); + .to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/normalize.css")); let swaydoc = self .module_info - .to_html_shorthand_path_string("assets/swaydoc.css"); + .to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/swaydoc.css")); let ayu = self .module_info - .to_html_shorthand_path_string("assets/ayu.css"); + .to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/ayu.css")); let sway_hjs = self .module_info - .to_html_shorthand_path_string("assets/highlight.js"); + .to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/highlight.js")); let ayu_hjs = self .module_info - .to_html_shorthand_path_string("assets/ayu.min.css"); + .to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/ayu.min.css")); let mut rendered_module_anchors = self.module_info.get_anchors()?; rendered_module_anchors.pop(); diff --git a/forc-plugins/forc-doc/src/render/item/components.rs b/forc-plugins/forc-doc/src/render/item/components.rs index 1c0d20b6e3a..1028d611c50 100644 --- a/forc-plugins/forc-doc/src/render/item/components.rs +++ b/forc-plugins/forc-doc/src/render/item/components.rs @@ -4,7 +4,7 @@ use crate::{ constant::IDENTITY, item::context::ItemContext, sidebar::*, title::DocBlockTitle, DocStyle, Renderable, }, - RenderPlan, + RenderPlan, ASSETS_DIR_NAME, }; use anyhow::Result; use horrorshow::{box_html, Raw, RenderBox}; @@ -28,11 +28,15 @@ impl Renderable for ItemHeader { item_name, } = self; - let favicon = module_info.to_html_shorthand_path_string("assets/sway-logo.svg"); - let normalize = module_info.to_html_shorthand_path_string("assets/normalize.css"); - let swaydoc = module_info.to_html_shorthand_path_string("assets/swaydoc.css"); - let ayu = module_info.to_html_shorthand_path_string("assets/ayu.css"); - let ayu_hjs = module_info.to_html_shorthand_path_string("assets/ayu.min.css"); + let favicon = + module_info.to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/sway-logo.svg")); + let normalize = + module_info.to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/normalize.css")); + let swaydoc = + module_info.to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/swaydoc.css")); + let ayu = module_info.to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/ayu.css")); + let ayu_hjs = + module_info.to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/ayu.min.css")); Ok(box_html! { head { @@ -107,7 +111,8 @@ impl Renderable for ItemBody { let item_context = (item_context.context_opt.is_some() || item_context.impl_traits.is_some()) .then(|| -> Result> { item_context.render(render_plan.clone()) }); - let sway_hjs = module_info.to_html_shorthand_path_string("assets/highlight.js"); + let sway_hjs = + module_info.to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/highlight.js")); let rendered_module_anchors = module_info.get_anchors()?; Ok(box_html! { diff --git a/forc-plugins/forc-doc/src/render/mod.rs b/forc-plugins/forc-doc/src/render/mod.rs index 1bd3061fab9..a9ae707005f 100644 --- a/forc-plugins/forc-doc/src/render/mod.rs +++ b/forc-plugins/forc-doc/src/render/mod.rs @@ -70,7 +70,7 @@ impl RenderedDocumentation { forc_version: Option, ) -> Result { let mut rendered_docs: RenderedDocumentation = Default::default(); - let root_module = match raw_docs.first() { + let root_module = match raw_docs.0.first() { Some(doc) => ModuleInfo::from_ty_module( vec![doc.module_info.project_name().to_owned()], root_attributes.map(|attrs_map| attrs_map.to_html_string()), @@ -84,7 +84,7 @@ impl RenderedDocumentation { }; let mut module_map: BTreeMap>> = BTreeMap::new(); - for doc in raw_docs { + for doc in raw_docs.0 { rendered_docs .0 .push(RenderedDocument::from_doc(&doc, render_plan.clone())?); diff --git a/forc-plugins/forc-doc/src/render/sidebar.rs b/forc-plugins/forc-doc/src/render/sidebar.rs index 28046c72e50..4894575a964 100644 --- a/forc-plugins/forc-doc/src/render/sidebar.rs +++ b/forc-plugins/forc-doc/src/render/sidebar.rs @@ -1,3 +1,6 @@ +use crate::ASSETS_DIR_NAME; +use std::path::PathBuf; + use crate::{ doc::module::ModuleInfo, render::{ @@ -41,7 +44,7 @@ impl Renderable for Sidebar { fn render(self, _render_plan: RenderPlan) -> Result> { let path_to_logo = self .module_info - .to_html_shorthand_path_string("assets/sway-logo.svg"); + .to_html_shorthand_path_string(&format!("{ASSETS_DIR_NAME}/sway-logo.svg")); let style = self.style.clone(); let version_opt = self.version_opt.clone(); let location_with_prefix = match &style { @@ -59,9 +62,15 @@ impl Renderable for Sidebar { format!("{} {}", title.item_title_str(), name.as_str()) } }; - let root_path = self - .module_info - .to_html_shorthand_path_string(INDEX_FILENAME); + let root_path = self.module_info.to_html_shorthand_path_string( + PathBuf::from(self.module_info.project_name()) + .join(INDEX_FILENAME) + .to_str() + .ok_or_else(|| anyhow::anyhow!( + "found invalid root file path for {}\nmake sure your project's name contains only valid unicode characters", + self.module_info.project_name(), + ))?, + ); let logo_path_to_root = match style { DocStyle::AllDoc(_) | DocStyle::Item { .. } | DocStyle::ModuleIndex => root_path, DocStyle::ProjectIndex(_) => IDENTITY.to_owned(), diff --git a/forc-plugins/forc-doc/src/assets/FiraSans-Medium.woff2 b/forc-plugins/forc-doc/src/static.files/FiraSans-Medium.woff2 similarity index 100% rename from forc-plugins/forc-doc/src/assets/FiraSans-Medium.woff2 rename to forc-plugins/forc-doc/src/static.files/FiraSans-Medium.woff2 diff --git a/forc-plugins/forc-doc/src/assets/FiraSans-Regular.woff2 b/forc-plugins/forc-doc/src/static.files/FiraSans-Regular.woff2 similarity index 100% rename from forc-plugins/forc-doc/src/assets/FiraSans-Regular.woff2 rename to forc-plugins/forc-doc/src/static.files/FiraSans-Regular.woff2 diff --git a/forc-plugins/forc-doc/src/assets/NanumBarunGothic.ttf.woff2 b/forc-plugins/forc-doc/src/static.files/NanumBarunGothic.ttf.woff2 similarity index 100% rename from forc-plugins/forc-doc/src/assets/NanumBarunGothic.ttf.woff2 rename to forc-plugins/forc-doc/src/static.files/NanumBarunGothic.ttf.woff2 diff --git a/forc-plugins/forc-doc/src/assets/SourceCodePro-It.ttf.woff2 b/forc-plugins/forc-doc/src/static.files/SourceCodePro-It.ttf.woff2 similarity index 100% rename from forc-plugins/forc-doc/src/assets/SourceCodePro-It.ttf.woff2 rename to forc-plugins/forc-doc/src/static.files/SourceCodePro-It.ttf.woff2 diff --git a/forc-plugins/forc-doc/src/assets/SourceCodePro-Regular.ttf.woff2 b/forc-plugins/forc-doc/src/static.files/SourceCodePro-Regular.ttf.woff2 similarity index 100% rename from forc-plugins/forc-doc/src/assets/SourceCodePro-Regular.ttf.woff2 rename to forc-plugins/forc-doc/src/static.files/SourceCodePro-Regular.ttf.woff2 diff --git a/forc-plugins/forc-doc/src/assets/SourceCodePro-Semibold.ttf.woff2 b/forc-plugins/forc-doc/src/static.files/SourceCodePro-Semibold.ttf.woff2 similarity index 100% rename from forc-plugins/forc-doc/src/assets/SourceCodePro-Semibold.ttf.woff2 rename to forc-plugins/forc-doc/src/static.files/SourceCodePro-Semibold.ttf.woff2 diff --git a/forc-plugins/forc-doc/src/assets/SourceSerif4-Bold.ttf.woff2 b/forc-plugins/forc-doc/src/static.files/SourceSerif4-Bold.ttf.woff2 similarity index 100% rename from forc-plugins/forc-doc/src/assets/SourceSerif4-Bold.ttf.woff2 rename to forc-plugins/forc-doc/src/static.files/SourceSerif4-Bold.ttf.woff2 diff --git a/forc-plugins/forc-doc/src/assets/SourceSerif4-It.ttf.woff2 b/forc-plugins/forc-doc/src/static.files/SourceSerif4-It.ttf.woff2 similarity index 100% rename from forc-plugins/forc-doc/src/assets/SourceSerif4-It.ttf.woff2 rename to forc-plugins/forc-doc/src/static.files/SourceSerif4-It.ttf.woff2 diff --git a/forc-plugins/forc-doc/src/assets/SourceSerif4-Regular.ttf.woff2 b/forc-plugins/forc-doc/src/static.files/SourceSerif4-Regular.ttf.woff2 similarity index 100% rename from forc-plugins/forc-doc/src/assets/SourceSerif4-Regular.ttf.woff2 rename to forc-plugins/forc-doc/src/static.files/SourceSerif4-Regular.ttf.woff2 diff --git a/forc-plugins/forc-doc/src/assets/ayu.css b/forc-plugins/forc-doc/src/static.files/ayu.css similarity index 100% rename from forc-plugins/forc-doc/src/assets/ayu.css rename to forc-plugins/forc-doc/src/static.files/ayu.css diff --git a/forc-plugins/forc-doc/src/assets/ayu.min.css b/forc-plugins/forc-doc/src/static.files/ayu.min.css similarity index 100% rename from forc-plugins/forc-doc/src/assets/ayu.min.css rename to forc-plugins/forc-doc/src/static.files/ayu.min.css diff --git a/forc-plugins/forc-doc/src/assets/clipboard.svg b/forc-plugins/forc-doc/src/static.files/clipboard.svg similarity index 100% rename from forc-plugins/forc-doc/src/assets/clipboard.svg rename to forc-plugins/forc-doc/src/static.files/clipboard.svg diff --git a/forc-plugins/forc-doc/src/assets/down-arrow.svg b/forc-plugins/forc-doc/src/static.files/down-arrow.svg similarity index 100% rename from forc-plugins/forc-doc/src/assets/down-arrow.svg rename to forc-plugins/forc-doc/src/static.files/down-arrow.svg diff --git a/forc-plugins/forc-doc/src/assets/highlight.js b/forc-plugins/forc-doc/src/static.files/highlight.js similarity index 100% rename from forc-plugins/forc-doc/src/assets/highlight.js rename to forc-plugins/forc-doc/src/static.files/highlight.js diff --git a/forc-plugins/forc-doc/src/assets/normalize.css b/forc-plugins/forc-doc/src/static.files/normalize.css similarity index 100% rename from forc-plugins/forc-doc/src/assets/normalize.css rename to forc-plugins/forc-doc/src/static.files/normalize.css diff --git a/forc-plugins/forc-doc/src/assets/sway-logo.svg b/forc-plugins/forc-doc/src/static.files/sway-logo.svg similarity index 100% rename from forc-plugins/forc-doc/src/assets/sway-logo.svg rename to forc-plugins/forc-doc/src/static.files/sway-logo.svg diff --git a/forc-plugins/forc-doc/src/assets/swaydoc.css b/forc-plugins/forc-doc/src/static.files/swaydoc.css similarity index 100% rename from forc-plugins/forc-doc/src/assets/swaydoc.css rename to forc-plugins/forc-doc/src/static.files/swaydoc.css diff --git a/forc-plugins/forc-doc/src/assets/toggle-minus.svg b/forc-plugins/forc-doc/src/static.files/toggle-minus.svg similarity index 100% rename from forc-plugins/forc-doc/src/assets/toggle-minus.svg rename to forc-plugins/forc-doc/src/static.files/toggle-minus.svg diff --git a/forc-plugins/forc-doc/src/assets/toggle-plus.svg b/forc-plugins/forc-doc/src/static.files/toggle-plus.svg similarity index 100% rename from forc-plugins/forc-doc/src/assets/toggle-plus.svg rename to forc-plugins/forc-doc/src/static.files/toggle-plus.svg diff --git a/forc-plugins/forc-doc/src/assets/wheel.svg b/forc-plugins/forc-doc/src/static.files/wheel.svg similarity index 100% rename from forc-plugins/forc-doc/src/assets/wheel.svg rename to forc-plugins/forc-doc/src/static.files/wheel.svg diff --git a/scripts/highlightjs/build.sh b/scripts/highlightjs/build.sh index ee4742db4fd..de827ddf709 100755 --- a/scripts/highlightjs/build.sh +++ b/scripts/highlightjs/build.sh @@ -14,7 +14,7 @@ rm -rf build node tools/build.js sway rust ini bash shell json cp build/highlight.min.js ../../../docs/reference/theme/highlight.js cp build/highlight.min.js ../../../docs/book/theme/highlight.js -cp build/highlight.min.js ../../../forc-plugins/forc-doc/src/assets/highlight.js +cp build/highlight.min.js ../../../forc-plugins/forc-doc/src/static.files/highlight.js # add "keep" in order to keep highlight.js repo if [[ ${1} != "keep" ]]; then