Skip to content

Commit

Permalink
Implement guide section
Browse files Browse the repository at this point in the history
Signed-off-by: Sergio Castaño Arteaga <[email protected]>
  • Loading branch information
tegioz committed Aug 26, 2023
1 parent 2bfccda commit 1d9af42
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 24 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ futures = "0.3.28"
hex = "0.4.3"
lazy_static = "1.4.0"
leaky-bucket = "1.0.1"
markdown = "1.0.0-alpha.12"
mime_guess = "2.0.4"
num_cpus = "1.16.0"
octorust = "0.3.2"
Expand Down
30 changes: 26 additions & 4 deletions src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ use crate::{
data::{get_landscape_data, LandscapeData},
datasets::Datasets,
github::collect_github_data,
guide::generate_guide_html,
logos::prepare_logo,
projects::{generate_projects_csv, Project, ProjectsMd},
settings::{get_landscape_settings, LandscapeSettings},
BuildArgs, LogosSource,
BuildArgs, GuideSource, LogosSource,
};
use anyhow::{format_err, Result};
use askama::Template;
Expand Down Expand Up @@ -71,6 +72,9 @@ pub(crate) async fn build(args: &BuildArgs) -> Result<()> {
landscape_data.add_featured_items_data(&settings)?;
landscape_data.add_member_subcategory(&settings.members_category);

// Prepare guide and copy it to the output directory
let includes_guide = prepare_guide(&args.guide_source, &args.output_dir).await?.is_some();

// Prepare logos and copy them to the output directory
prepare_logos(&cache, &args.logos_source, &mut landscape_data, &args.output_dir).await?;

Expand All @@ -88,7 +92,7 @@ pub(crate) async fn build(args: &BuildArgs) -> Result<()> {
let datasets = generate_datasets(&landscape_data, &settings, &args.output_dir)?;

// Render index file and write it to the output directory
render_index(&datasets, &args.output_dir)?;
render_index(&datasets, includes_guide, &args.output_dir)?;

// Copy web assets files to the output directory
copy_web_assets(&args.output_dir)?;
Expand Down Expand Up @@ -183,6 +187,19 @@ fn generate_projects_files(landscape_data: &LandscapeData, output_dir: &Path) ->
Ok(())
}

/// Prepare guide and copy it to the output directory.
#[instrument(skip_all, err)]
async fn prepare_guide(guide_source: &GuideSource, output_dir: &Path) -> Result<Option<()>> {
debug!("preparing guide");

let Some(guide_html) = generate_guide_html(guide_source).await? else {
return Ok(None);
};
let path = output_dir.join(DOCS_PATH).join("guide.html");
File::create(path)?.write_all(guide_html.as_bytes())?;
Ok(Some(()))
}

/// Prepare logos and copy them to the output directory, updating the logo
/// reference on each landscape item.
#[instrument(skip_all, err)]
Expand Down Expand Up @@ -257,13 +274,18 @@ async fn prepare_logos(
#[template(path = "index.html", escape = "none")]
struct Index<'a> {
pub datasets: &'a Datasets,
pub includes_guide: bool,
}

/// Render index file and write it to the output directory.
#[instrument(skip_all, err)]
fn render_index(datasets: &Datasets, output_dir: &Path) -> Result<()> {
fn render_index(datasets: &Datasets, includes_guide: bool, output_dir: &Path) -> Result<()> {
debug!("rendering index.html file");
let index = Index { datasets }.render()?;
let index = Index {
datasets,
includes_guide,
}
.render()?;
let mut file = File::create(output_dir.join("index.html"))?;
file.write_all(index.as_bytes())?;

Expand Down
18 changes: 11 additions & 7 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,19 @@ pub const DATE_FORMAT: &str = "%Y-%m-%d";
/// Get landscape data from the source provided.
#[instrument(skip_all, err)]
pub(crate) async fn get_landscape_data(src: &DataSource) -> Result<LandscapeData> {
let data = if let Some(file) = &src.data_file {
// Try from file
if let Some(file) = &src.data_file {
debug!(?file, "getting landscape data from file");
LandscapeData::new_from_file(file)
} else {
debug!(url = ?src.data_url.as_ref().unwrap(), "getting landscape data from url");
LandscapeData::new_from_url(src.data_url.as_ref().unwrap()).await
}?;
return LandscapeData::new_from_file(file);
};

Ok(data)
// Try from url
if let Some(url) = &src.data_url {
debug!(?url, "getting landscape data from url");
return LandscapeData::new_from_url(url).await;
};

Err(format_err!("data file or url not provided"))
}

/// Landscape data.
Expand Down
55 changes: 55 additions & 0 deletions src/guide.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use crate::GuideSource;
use anyhow::{format_err, Result};
use reqwest::StatusCode;
use std::fs;
use tracing::{debug, instrument};

/// Generate an HTML document with the guide content from the guide in markdown
/// format available in the source provided.
#[instrument(skip_all, err)]
pub(crate) async fn generate_guide_html(src: &GuideSource) -> Result<Option<String>> {
// Get guide in markdown format
let Some(guide_md) = get_guide_md(src).await? else {
return Ok(None);
};

// Convert markdown to HTML
let guide_html = markdown::to_html_with_options(
&guide_md,
&markdown::Options {
compile: markdown::CompileOptions {
allow_dangerous_html: true,
..markdown::CompileOptions::default()
},
..markdown::Options::default()
},
)
.map_err(|err| format_err!("{err}"))?;

Ok(Some(guide_html))
}

/// Get guide in markdown format.
#[instrument(skip_all, err)]
pub(crate) async fn get_guide_md(src: &GuideSource) -> Result<Option<String>> {
// Try from file
if let Some(file) = &src.guide_file {
debug!(?file, "getting landscape guide from file");
return Ok(Some(fs::read_to_string(file)?));
};

// Try from url
if let Some(url) = &src.guide_url {
debug!(?url, "getting landscape guide from url");
let resp = reqwest::get(url).await?;
if resp.status() != StatusCode::OK {
return Err(format_err!(
"unexpected status code getting landscape guide file: {}",
resp.status()
));
}
return Ok(Some(resp.text().await?));
};

Ok(None)
}
16 changes: 10 additions & 6 deletions src/logos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,14 @@ async fn get_svg(
logos_source: &LogosSource,
file_name: &str,
) -> Result<Vec<u8>> {
let svg_data = if let Some(path) = &logos_source.logos_path {
fs::read(path.join(file_name))?
} else {
let logos_url = logos_source.logos_url.as_ref().unwrap().trim_end_matches('/');
// Try from path
if let Some(path) = &logos_source.logos_path {
return fs::read(path.join(file_name)).map_err(Into::into);
};

// Try from url
if let Some(logos_url) = &logos_source.logos_url {
let logos_url = logos_url.trim_end_matches('/');
let logo_url = format!("{logos_url}/{file_name}");
let resp = http_client.get(logo_url).send().await?;
if resp.status() != StatusCode::OK {
Expand All @@ -93,10 +97,10 @@ async fn get_svg(
resp.status()
));
}
resp.bytes().await?.to_vec()
return Ok(resp.bytes().await?.to_vec());
};

Ok(svg_data)
Err(format_err!("logos path or url not provided"))
}

/// Get SVG bounding box (smallest rectangle in which the object fits).
Expand Down
18 changes: 18 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mod crunchbase;
mod data;
mod datasets;
mod github;
mod guide;
mod logos;
mod projects;
mod s3;
Expand Down Expand Up @@ -51,6 +52,10 @@ struct BuildArgs {
#[command(flatten)]
data_source: DataSource,

/// Guide source.
#[command(flatten)]
guide_source: GuideSource,

/// Logos source.
#[command(flatten)]
logos_source: LogosSource,
Expand All @@ -77,6 +82,19 @@ struct DataSource {
data_url: Option<String>,
}

/// Landscape guide location.
#[derive(Args)]
#[group(required = false, multiple = false)]
struct GuideSource {
/// Landscape guide file local path.
#[arg(long)]
guide_file: Option<PathBuf>,

/// Landscape guide file url.
#[arg(long)]
guide_url: Option<String>,
}

/// Landscape logos location.
#[derive(Args, Clone)]
#[group(required = true, multiple = false)]
Expand Down
18 changes: 11 additions & 7 deletions src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,19 @@ use tracing::{debug, instrument};
/// Get landscape settings from the source provided.
#[instrument(skip_all, err)]
pub(crate) async fn get_landscape_settings(src: &SettingsSource) -> Result<LandscapeSettings> {
let settings = if let Some(file) = &src.settings_file {
// Try from file
if let Some(file) = &src.settings_file {
debug!(?file, "getting landscape settings from file");
LandscapeSettings::new_from_file(file)
} else {
debug!(url = ?src.settings_url.as_ref().unwrap(), "getting landscape settings from url");
LandscapeSettings::new_from_url(src.settings_url.as_ref().unwrap()).await
}?;
return LandscapeSettings::new_from_file(file);
};

Ok(settings)
// Try from url
if let Some(url) = &src.settings_url {
debug!(?url, "getting landscape settings from url");
return LandscapeSettings::new_from_url(url).await;
};

Err(format_err!("settings file or url not provided"))
}

/// Landscape settings.
Expand Down
1 change: 1 addition & 0 deletions web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<% } else { %>
<script>
window.baseDS = {{ datasets.base|json|safe }};
window.includesGuide = {{ includes_guide }};
</script>
<% } %>
</head>
Expand Down

0 comments on commit 1d9af42

Please sign in to comment.