ddoc/init/
init_hjson.rs

1use {
2    crate::*,
3    std::{
4        borrow::Cow,
5        fs,
6        path::Path,
7    },
8};
9
10static TEMPLATE_INIT_HJSON: &str = r#"
11# This is a configuration file for the ddoc static site generator.
12# For details and instructions, see https://dystroy.org/ddoc/
13
14title: <title>
15description: <description>
16favicon: null // eg "img/favicon.ico"
17ddoc-version: "<ddoc-version>" // minimum required ddoc version to build this site
18
19// All pages must be listed here
20// One of them must be index.md
21// You can have submenus, eg:
22// pages: {
23//     Home: index.md
24//     Guide: {
25//         "Getting Started": guide/getting_started.md
26//         "Advanced Topics": guide/advanced_topics.md
27//     }
28// }
29site-map: {
30    Home: index.md
31}
32
33// This describes the content of the <body> element of each page.
34// Elements starting with 'ddoc-' will be replaced by special items:
35// links, page TOC, global menu, main HTML translated from markdown, etc.
36//
37// Links (ddoc-link) can have { img, inline, href, label, alt, target}.
38// All these fields are optional.
39// Hrefs starting with '/' are relative to the site's root (eg '/guide/help.md')
40body: {
41    header: {
42        nav.before-menu: {
43            // this is a good place for a logo or a link to a wider site
44        }
45        ddoc-menu: {
46            // if true, the generated HTML includes a checkbox which
47            // can be styled into a hamburger menu for small screens
48            hamburger-checkbox: true
49        }
50        nav.after-menu: {
51            ddoc-link.previous-page-link: {
52                inline: img/ddoc-left-arrow.svg
53                href: --previous
54            }
55            ddoc-link.search-opener: {
56                inline: img/ddoc-search.svg
57                href: --search
58            }
59            ddoc-link.next-page-link: {
60                inline: img/ddoc-right-arrow.svg
61                href: --next
62            }
63            <github-navlink>
64        }
65    }
66    article: {
67        aside.page-nav: {
68            ddoc-toc: {
69                // if true, a script is injected to highlight the part the user
70                // is currently viewing (the 'active' class is added to the
71                // corresponding TOC item)
72                activate-visible-item: true
73            }
74        }
75        ddoc-main: {}
76    }
77    footer: {
78    }
79}
80
81"#;
82static TEMPLATE_GITHUB_NAVLINK: &str = r#"ddoc-link.external-nav-link: {
83                inline: img/github-mark.svg
84                alt: GitHub
85                href: <url>
86            }"#;
87
88/// Initialize a ddoc.hjson file in the specified directory
89/// (do nothing if one already exists)
90///
91/// # Errors
92/// Return `DdError::InvalidConfig` if an existing ddoc.hjson
93/// cannot be read, or other less likely `DdError` variants on
94/// write errors when creating a new ddoc.hjson
95pub fn init_hjson_in_dir(
96    dir: &Path,
97    init_values: &InitValues,
98) -> DdResult<Config> {
99    let path = dir.join("ddoc.hjson");
100    if path.exists() {
101        read_file(&path).map_err(|e| {
102            error!("Error reading {}: {}", path.display(), e);
103            // Return a specific error so that the caller can
104            // issue a proper message to the user
105            DdError::InvalidConfig
106        })
107    } else {
108        // FIXME we should handle the case of this generation failing
109        // to build a parsable hjson (then probably give up with the
110        // init values)
111        let mut hjson = TEMPLATE_INIT_HJSON.to_owned();
112        let title = init_values.title.as_deref().unwrap_or("Unnamed Site");
113        let description = init_values.description.as_deref().unwrap_or("");
114        let github_navlink = if let Some(github_repo) = &init_values.github_repo {
115            TEMPLATE_GITHUB_NAVLINK.replace("<url>", github_repo).into()
116        } else {
117            Cow::Borrowed("// links here will appear after the menu")
118        };
119
120        hjson = hjson
121            .replace("<title>", &escape_hjson_string(title))
122            .replace("<description>", &escape_hjson_string(description))
123            .replace("<ddoc-version>", DDOC_VERSION)
124            .replace("<github-navlink>", &github_navlink);
125
126        fs::write(&path, hjson)?;
127        eprintln!("Created {}", path.display());
128        read_file(&path)
129    }
130}
131
132pub fn escape_hjson_string(s: &str) -> String {
133    format!("{:?}", s)
134}