Render Markdown in option docs for flakes and longDescription (#539)
This commit is contained in:
parent
e7ceafb0d4
commit
ba0b05b998
5
flake-info/Cargo.lock
generated
5
flake-info/Cargo.lock
generated
|
@ -341,7 +341,6 @@ dependencies = [
|
|||
"serde_path_to_error",
|
||||
"sha2",
|
||||
"structopt",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"toml",
|
||||
|
@ -866,9 +865,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pandoc"
|
||||
version = "0.8.8"
|
||||
version = "0.8.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eac785b7de8de25c5ec48b3a9df1be552de03906f99145ed6d7da3d696c0dbb"
|
||||
checksum = "2eb8469d27ed9fd7925629076a3675fea964c3f44c49662bdf549a8b7ddf0820"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
]
|
||||
|
|
|
@ -18,13 +18,12 @@ structopt = "0.3"
|
|||
command-run = "0.13"
|
||||
env_logger = "0.9"
|
||||
log = "0.4"
|
||||
tempfile = "3"
|
||||
lazy_static = "1.4"
|
||||
fancy-regex = "0.6"
|
||||
tokio = { version = "*", features = ["full"] }
|
||||
reqwest = { version = "0.11", features = ["json", "blocking"] }
|
||||
sha2 = "0.9"
|
||||
pandoc = "0.8"
|
||||
pandoc = "0.8.10"
|
||||
semver = "1.0"
|
||||
|
||||
elasticsearch = {git = "https://github.com/elastic/elasticsearch-rs", features = ["rustls-tls"], optional = true}
|
||||
|
|
|
@ -19,6 +19,7 @@ let
|
|||
readPackages = system: drvs: lib.mapAttrsToList (
|
||||
attribute_name: drv: (
|
||||
{
|
||||
entry_type = "package";
|
||||
attribute_name = attribute_name;
|
||||
system = system;
|
||||
name = drv.name;
|
||||
|
@ -35,6 +36,7 @@ let
|
|||
readApps = system: apps: lib.mapAttrsToList (
|
||||
attribute_name: app: (
|
||||
{
|
||||
entry_type = "app";
|
||||
attribute_name = attribute_name;
|
||||
system = system;
|
||||
}
|
||||
|
@ -86,6 +88,7 @@ let
|
|||
x;
|
||||
in
|
||||
opt
|
||||
// { entry_type = "option"; }
|
||||
// applyOnAttr "default" substFunction
|
||||
// applyOnAttr "example" substFunction # (_: { __type = "function"; })
|
||||
// applyOnAttr "type" substFunction
|
|
@ -23,16 +23,17 @@ pkgs.rustPlatform.buildRustPackage rec {
|
|||
|
||||
checkInputs = with pkgs; [ pandoc ];
|
||||
|
||||
ROOTDIR = builtins.placeholder "out";
|
||||
NIXPKGS_PANDOC_FILTERS_PATH = "${pkgs.path + "/doc/build-aux/pandoc-filters"}";
|
||||
|
||||
checkFlags = [
|
||||
"--skip elastic::tests"
|
||||
"--skip nix_gc::tests"
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
cp -rt "$out" assets
|
||||
|
||||
wrapProgram $out/bin/flake-info \
|
||||
--set NIXPKGS_PANDOC_FILTERS_PATH "${NIXPKGS_PANDOC_FILTERS_PATH}" \
|
||||
--set NIXOS_CHANNELS '${builtins.toJSON nixosChannels}' \
|
||||
--prefix PATH : ${pkgs.pandoc}/bin
|
||||
'';
|
||||
|
|
|
@ -6,3 +6,10 @@ pub use nix_check_version::{check_nix_version, NixCheckError};
|
|||
pub use nix_flake_attrs::get_derivation_info;
|
||||
pub use nix_flake_info::get_flake_info;
|
||||
pub use nixpkgs_info::{get_nixpkgs_info, get_nixpkgs_options};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use std::path::PathBuf;
|
||||
|
||||
lazy_static! {
|
||||
static ref EXTRACT_SCRIPT: PathBuf = crate::DATADIR.join("commands/flake_info.nix");
|
||||
}
|
||||
|
|
|
@ -3,11 +3,8 @@ use anyhow::{Context, Result};
|
|||
use command_run::{Command, LogTo};
|
||||
use serde_json::Deserializer;
|
||||
use std::fmt::Display;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const SCRIPT: &str = include_str!("flake_info.nix");
|
||||
const ARGS: [&str; 4] = [
|
||||
"eval",
|
||||
"--json",
|
||||
|
@ -23,12 +20,8 @@ pub fn get_derivation_info<T: AsRef<str> + Display>(
|
|||
temp_store: bool,
|
||||
extra: &[String],
|
||||
) -> Result<Vec<FlakeEntry>> {
|
||||
let script_dir = tempfile::tempdir()?;
|
||||
let script_path = script_dir.path().join("extract.nix");
|
||||
writeln!(File::create(&script_path)?, "{}", SCRIPT)?;
|
||||
|
||||
let mut command = Command::with_args("nix", ARGS.iter());
|
||||
command.add_arg_pair("-f", script_path.as_os_str());
|
||||
command.add_arg_pair("-f", super::EXTRACT_SCRIPT.clone());
|
||||
command.add_arg_pair("-I", "nixpkgs=channel:nixpkgs-unstable");
|
||||
command.add_args(["--override-flake", "input-flake", flake_ref.as_ref()].iter());
|
||||
command.add_args(["--argstr", "flake", flake_ref.as_ref()].iter());
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
use anyhow::{Context, Result};
|
||||
use serde_json::Deserializer;
|
||||
use std::io::Write;
|
||||
use std::{collections::HashMap, fmt::Display, fs::File};
|
||||
use std::{collections::HashMap, fmt::Display};
|
||||
|
||||
use command_run::{Command, LogTo};
|
||||
use log::error;
|
||||
|
||||
use crate::data::import::{NixOption, NixpkgsEntry, Package};
|
||||
|
||||
const FLAKE_INFO_SCRIPT: &str = include_str!("flake_info.nix");
|
||||
|
||||
pub fn get_nixpkgs_info<T: AsRef<str> + Display>(nixpkgs_channel: T) -> Result<Vec<NixpkgsEntry>> {
|
||||
let mut command = Command::new("nix-env");
|
||||
command.add_args(&[
|
||||
|
@ -54,20 +51,10 @@ pub fn get_nixpkgs_info<T: AsRef<str> + Display>(nixpkgs_channel: T) -> Result<V
|
|||
pub fn get_nixpkgs_options<T: AsRef<str> + Display>(
|
||||
nixpkgs_channel: T,
|
||||
) -> Result<Vec<NixpkgsEntry>> {
|
||||
let script_dir = tempfile::tempdir()?;
|
||||
let script_path = script_dir.path().join("flake_info.nix");
|
||||
writeln!(File::create(&script_path)?, "{}", FLAKE_INFO_SCRIPT)?;
|
||||
|
||||
let mut command = Command::new("nix");
|
||||
command.add_args(&[
|
||||
"eval",
|
||||
"--json",
|
||||
"-f",
|
||||
script_path.to_str().unwrap(),
|
||||
"-I",
|
||||
format!("nixpkgs={}", nixpkgs_channel.as_ref()).as_str(),
|
||||
"nixos-options",
|
||||
]);
|
||||
let mut command = Command::with_args("nix", &["eval", "--json"]);
|
||||
command.add_arg_pair("-f", super::EXTRACT_SCRIPT.clone());
|
||||
command.add_arg_pair("-I", format!("nixpkgs={}", nixpkgs_channel.as_ref()));
|
||||
command.add_arg("nixos-options");
|
||||
|
||||
command.enable_capture();
|
||||
command.log_to = LogTo::Log;
|
||||
|
|
|
@ -6,26 +6,14 @@ use std::{
|
|||
path::PathBuf,
|
||||
};
|
||||
|
||||
use super::{
|
||||
import::{DocValue, ModulePath},
|
||||
pandoc::PandocExt,
|
||||
};
|
||||
use crate::data::import::NixOption;
|
||||
use anyhow::Context;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{
|
||||
import,
|
||||
import::{self, DocString, DocValue, ModulePath, NixOption},
|
||||
pandoc::PandocExt,
|
||||
system::System,
|
||||
utility::{AttributeQuery, Flatten, OneOrMany, Reverse},
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
lazy_static! {
|
||||
static ref FILTERS_PATH: PathBuf = std::env::var("NIXPKGS_PANDOC_FILTERS_PATH")
|
||||
.unwrap_or("".into())
|
||||
.into();
|
||||
}
|
||||
|
||||
type Flake = super::Flake;
|
||||
|
||||
|
@ -107,8 +95,7 @@ pub enum Derivation {
|
|||
option_name_query: AttributeQuery,
|
||||
option_name_query_reverse: Reverse<AttributeQuery>,
|
||||
|
||||
option_description: Option<String>,
|
||||
option_description_reverse: Option<Reverse<String>>,
|
||||
option_description: Option<DocString>,
|
||||
|
||||
option_type: Option<String>,
|
||||
|
||||
|
@ -147,7 +134,12 @@ impl TryFrom<(import::FlakeEntry, super::Flake)> for Derivation {
|
|||
|
||||
let package_attr_set_reverse = Reverse(package_attr_set.clone());
|
||||
|
||||
let package_license: Vec<License> = vec![license.into()];
|
||||
let package_license: Vec<License> = license
|
||||
.map(OneOrMany::into_list)
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|sos| sos.0.into())
|
||||
.collect();
|
||||
let package_license_set: Vec<String> = package_license
|
||||
.iter()
|
||||
.clone()
|
||||
|
@ -215,7 +207,7 @@ impl TryFrom<import::NixpkgsEntry> for Derivation {
|
|||
|
||||
let package_attr_set_reverse = Reverse(package_attr_set.clone());
|
||||
|
||||
let package_license: Vec<_> = package
|
||||
let package_license: Vec<License> = package
|
||||
.meta
|
||||
.license
|
||||
.map(OneOrMany::into_list)
|
||||
|
@ -242,6 +234,12 @@ impl TryFrom<import::NixpkgsEntry> for Derivation {
|
|||
.flat_map(|m| m.name.to_owned())
|
||||
.collect();
|
||||
|
||||
let long_description = package
|
||||
.meta
|
||||
.long_description
|
||||
.map(|s| s.render_markdown())
|
||||
.transpose()?;
|
||||
|
||||
let position: Option<String> = package.meta.position.map(|p| {
|
||||
if p.starts_with("/nix/store") {
|
||||
p.split("/").skip(4).collect::<Vec<&str>>().join("/")
|
||||
|
@ -273,8 +271,8 @@ impl TryFrom<import::NixpkgsEntry> for Derivation {
|
|||
package_maintainers_set,
|
||||
package_description: package.meta.description.clone(),
|
||||
package_description_reverse: package.meta.description.map(Reverse),
|
||||
package_longDescription: package.meta.long_description.clone(),
|
||||
package_longDescription_reverse: package.meta.long_description.map(Reverse),
|
||||
package_longDescription: long_description.clone(),
|
||||
package_longDescription_reverse: long_description.map(Reverse),
|
||||
package_hydra: (),
|
||||
package_system: package.system,
|
||||
package_homepage: package
|
||||
|
@ -303,32 +301,13 @@ impl TryFrom<import::NixOption> for Derivation {
|
|||
flake,
|
||||
}: import::NixOption,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let description = description
|
||||
.as_ref()
|
||||
.map(PandocExt::render)
|
||||
.transpose()
|
||||
.with_context(|| format!("While rendering the description for option `{}`", name))?;
|
||||
let option_default = default;
|
||||
// .map(TryInto::try_into)
|
||||
// .transpose()
|
||||
// .with_context(|| format!("While rendering the default for option `{}`", name))?;
|
||||
let option_example = example;
|
||||
// .map(TryInto::try_into)
|
||||
// .transpose()
|
||||
// .with_context(|| format!("While rendering the example for option `{}`", name))?;
|
||||
let option_type = option_type;
|
||||
// .map(TryInto::try_into)
|
||||
// .transpose()
|
||||
// .with_context(|| format!("While rendering the type for option `{}`", name))?;
|
||||
|
||||
Ok(Derivation::Option {
|
||||
option_source: declarations.get(0).map(Clone::clone),
|
||||
option_name: name.clone(),
|
||||
option_name_reverse: Reverse(name.clone()),
|
||||
option_description: description.clone(),
|
||||
option_description_reverse: description.map(Reverse),
|
||||
option_default,
|
||||
option_example,
|
||||
option_description: description,
|
||||
option_default: default,
|
||||
option_example: example,
|
||||
option_flake: flake,
|
||||
option_type,
|
||||
option_name_query: AttributeQuery::new(&name),
|
||||
|
|
|
@ -16,7 +16,7 @@ use super::utility::{Flatten, OneOrMany};
|
|||
|
||||
/// Holds information about a specific derivation
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
#[serde(tag = "entry_type", rename_all = "lowercase")]
|
||||
pub enum FlakeEntry {
|
||||
/// A package as it may be defined in a flake
|
||||
///
|
||||
|
@ -31,8 +31,7 @@ pub enum FlakeEntry {
|
|||
outputs: Vec<String>,
|
||||
default_output: String,
|
||||
description: Option<String>,
|
||||
#[serde(deserialize_with = "string_or_struct", default)]
|
||||
license: License,
|
||||
license: Option<OneOrMany<StringOrStruct<License>>>,
|
||||
},
|
||||
/// An "application" that can be called using nix run <..>
|
||||
App {
|
||||
|
@ -52,7 +51,7 @@ pub struct NixOption {
|
|||
/// Location of the defining module(s)
|
||||
pub declarations: Vec<String>,
|
||||
|
||||
pub description: Option<String>,
|
||||
pub description: Option<DocString>,
|
||||
pub name: String,
|
||||
|
||||
#[serde(rename = "type")]
|
||||
|
@ -79,6 +78,20 @@ pub enum ModulePath {
|
|||
NamedModule((String, String)),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum DocString {
|
||||
DocFormat(DocFormat),
|
||||
String(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||
#[serde(tag = "_type", content = "text")]
|
||||
pub enum DocFormat {
|
||||
#[serde(rename = "mdDoc")]
|
||||
MarkdownDoc(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum DocValue {
|
||||
|
@ -89,12 +102,34 @@ pub enum DocValue {
|
|||
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||
#[serde(tag = "_type", content = "text")]
|
||||
pub enum Literal {
|
||||
#[serde(rename = "literalExpression")]
|
||||
#[serde(rename = "literalExpression", alias = "literalExample")]
|
||||
LiteralExpression(String),
|
||||
#[serde(rename = "literalExample")]
|
||||
LiteralExample(String),
|
||||
#[serde(rename = "literalDocBook")]
|
||||
LiteralDocBook(String),
|
||||
#[serde(rename = "literalMD")]
|
||||
LiteralMarkdown(String),
|
||||
}
|
||||
|
||||
impl Serialize for DocString {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match self {
|
||||
DocString::String(db) => {
|
||||
serializer.serialize_str(&db.render_docbook().unwrap_or_else(|e| {
|
||||
warn!("Could not render DocBook content: {}", e);
|
||||
db.to_owned()
|
||||
}))
|
||||
}
|
||||
DocString::DocFormat(DocFormat::MarkdownDoc(md)) => {
|
||||
serializer.serialize_str(&md.render_markdown().unwrap_or_else(|e| {
|
||||
warn!("Could not render Markdown content: {}", e);
|
||||
md.to_owned()
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for DocValue {
|
||||
|
@ -103,14 +138,18 @@ impl Serialize for DocValue {
|
|||
S: Serializer,
|
||||
{
|
||||
match self {
|
||||
DocValue::Literal(Literal::LiteralExample(s) | Literal::LiteralExpression(s)) => {
|
||||
return serializer.serialize_str(&s);
|
||||
DocValue::Literal(Literal::LiteralExpression(s)) => serializer.serialize_str(&s),
|
||||
DocValue::Literal(Literal::LiteralDocBook(db)) => {
|
||||
serializer.serialize_str(&db.render_docbook().unwrap_or_else(|e| {
|
||||
warn!("Could not render DocBook content: {}", e);
|
||||
db.to_owned()
|
||||
}))
|
||||
}
|
||||
DocValue::Literal(Literal::LiteralDocBook(doc_book)) => {
|
||||
return serializer.serialize_str(&doc_book.render().unwrap_or_else(|e| {
|
||||
warn!("Could not render docbook content: {}", e);
|
||||
doc_book.to_owned()
|
||||
}));
|
||||
DocValue::Literal(Literal::LiteralMarkdown(md)) => {
|
||||
serializer.serialize_str(&md.render_markdown().unwrap_or_else(|e| {
|
||||
warn!("Could not render Markdown content: {}", e);
|
||||
md.to_owned()
|
||||
}))
|
||||
}
|
||||
DocValue::Value(v) => serializer.serialize_str(&print_value(v.to_owned())),
|
||||
}
|
||||
|
|
|
@ -1,48 +1,34 @@
|
|||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use pandoc::{
|
||||
InputFormat, InputKind, OutputFormat, OutputKind, PandocError, PandocOption, PandocOutput,
|
||||
};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
const XREF_FILTER: &str = include_str!("fix-xrefs.lua");
|
||||
use pandoc::*;
|
||||
|
||||
const FILTERS_PATH: &str = env!("NIXPKGS_PANDOC_FILTERS_PATH");
|
||||
|
||||
lazy_static! {
|
||||
static ref FILTERS_PATH: PathBuf = std::env::var("NIXPKGS_PANDOC_FILTERS_PATH")
|
||||
.unwrap_or("".into())
|
||||
.into();
|
||||
static ref DOCBOOK_ROLES_FILTER: PathBuf =
|
||||
Path::new(FILTERS_PATH).join("docbook-reader/citerefentry-to-rst-role.lua");
|
||||
static ref MARKDOWN_ROLES_FILTER: PathBuf =
|
||||
Path::new(FILTERS_PATH).join("myst-reader/roles.lua");
|
||||
static ref MANPAGE_LINK_FILTER: PathBuf =
|
||||
Path::new(FILTERS_PATH).join("link-unix-man-references.lua");
|
||||
static ref XREF_FILTER: PathBuf = crate::DATADIR.join("data/fix-xrefs.lua");
|
||||
}
|
||||
|
||||
pub trait PandocExt {
|
||||
fn render(&self) -> Result<String, PandocError>;
|
||||
fn render_docbook(&self) -> Result<String, PandocError>;
|
||||
fn render_markdown(&self) -> Result<String, PandocError>;
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>> PandocExt for T {
|
||||
fn render(&self) -> Result<String, PandocError> {
|
||||
fn render_docbook(&self) -> Result<String, PandocError> {
|
||||
if !self.as_ref().contains("<") {
|
||||
return Ok(format!(
|
||||
"<rendered-docbook>{}</rendered-docbook>",
|
||||
"<rendered-html><p>{}</p></rendered-html>",
|
||||
self.as_ref()
|
||||
));
|
||||
}
|
||||
|
||||
let citeref_filter = {
|
||||
let mut p = FILTERS_PATH.clone();
|
||||
p.push("docbook-reader/citerefentry-to-rst-role.lua");
|
||||
p
|
||||
};
|
||||
let man_filter = {
|
||||
let mut p = FILTERS_PATH.clone();
|
||||
p.push("link-unix-man-references.lua");
|
||||
p
|
||||
};
|
||||
let tmpdir = tempfile::tempdir()?;
|
||||
let xref_filter = tmpdir.path().join("fix-xrefs.lua");
|
||||
writeln!(File::create(&xref_filter)?, "{}", XREF_FILTER)?;
|
||||
|
||||
let mut pandoc = pandoc::new();
|
||||
let wrapper_xml = format!(
|
||||
"
|
||||
<xml xmlns:xlink=\"http://www.w3.org/1999/xlink\">
|
||||
|
@ -52,19 +38,52 @@ impl<T: AsRef<str>> PandocExt for T {
|
|||
self.as_ref()
|
||||
);
|
||||
|
||||
let mut pandoc = pandoc::new();
|
||||
pandoc.set_input(InputKind::Pipe(wrapper_xml));
|
||||
pandoc.set_input_format(InputFormat::DocBook, Vec::new());
|
||||
pandoc.set_output(OutputKind::Pipe);
|
||||
pandoc.set_output_format(OutputFormat::Html, Vec::new());
|
||||
pandoc.add_options(&[
|
||||
PandocOption::LuaFilter(citeref_filter),
|
||||
PandocOption::LuaFilter(man_filter),
|
||||
PandocOption::LuaFilter(xref_filter),
|
||||
PandocOption::LuaFilter(DOCBOOK_ROLES_FILTER.clone()),
|
||||
PandocOption::LuaFilter(MANPAGE_LINK_FILTER.clone()),
|
||||
PandocOption::LuaFilter(XREF_FILTER.clone()),
|
||||
]);
|
||||
|
||||
pandoc.execute().map(|result| match result {
|
||||
PandocOutput::ToBuffer(description) => {
|
||||
format!("<rendered-docbook>{}</rendered-docbook>", description)
|
||||
PandocOutput::ToBuffer(html) => {
|
||||
format!("<rendered-html>{}</rendered-html>", html)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
fn render_markdown(&self) -> Result<String, PandocError> {
|
||||
let mut pandoc = pandoc::new();
|
||||
pandoc.set_input(InputKind::Pipe(self.as_ref().into()));
|
||||
pandoc.set_input_format(
|
||||
InputFormat::Commonmark,
|
||||
[
|
||||
MarkdownExtension::Attributes,
|
||||
MarkdownExtension::BracketedSpans,
|
||||
MarkdownExtension::DefinitionLists,
|
||||
MarkdownExtension::FencedDivs,
|
||||
MarkdownExtension::PipeTables,
|
||||
MarkdownExtension::RawAttribute,
|
||||
MarkdownExtension::Smart,
|
||||
]
|
||||
.to_vec(),
|
||||
);
|
||||
pandoc.set_output(OutputKind::Pipe);
|
||||
pandoc.set_output_format(OutputFormat::Html, Vec::new());
|
||||
pandoc.add_options(&[
|
||||
PandocOption::LuaFilter(MARKDOWN_ROLES_FILTER.clone()),
|
||||
PandocOption::LuaFilter(MANPAGE_LINK_FILTER.clone()),
|
||||
PandocOption::LuaFilter(XREF_FILTER.clone()),
|
||||
]);
|
||||
|
||||
pandoc.execute().map(|result| match result {
|
||||
PandocOutput::ToBuffer(html) => {
|
||||
format!("<rendered-html>{}</rendered-html>", html)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
})
|
||||
|
|
|
@ -174,11 +174,6 @@ lazy_static! {
|
|||
"analyzer": "english",
|
||||
"fields": {"edge": {"type": "text", "analyzer": "edge"}},
|
||||
},
|
||||
"option_description_reverse": {
|
||||
"type": "text",
|
||||
"analyzer": "english",
|
||||
"fields": {"edge": {"type": "text", "analyzer": "edge"}},
|
||||
},
|
||||
"option_type": {"type": "keyword"},
|
||||
"option_default": {"type": "text"},
|
||||
"option_example": {"type": "text"},
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
use anyhow::Result;
|
||||
use data::{import::Kind, Export, Flake, Source};
|
||||
use lazy_static::lazy_static;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub mod commands;
|
||||
pub mod data;
|
||||
|
@ -12,6 +14,11 @@ pub mod elastic;
|
|||
pub use commands::get_flake_info;
|
||||
use log::trace;
|
||||
|
||||
lazy_static! {
|
||||
static ref DATADIR: PathBuf =
|
||||
Path::new(option_env!("ROOTDIR").unwrap_or(env!("CARGO_MANIFEST_DIR"))).join("assets");
|
||||
}
|
||||
|
||||
pub fn process_flake(
|
||||
source: &Source,
|
||||
kind: &data::import::Kind,
|
||||
|
|
|
@ -39,8 +39,6 @@ import Html.Events
|
|||
exposing
|
||||
( onClick
|
||||
)
|
||||
import Html.Parser
|
||||
import Html.Parser.Util
|
||||
import Http exposing (Body)
|
||||
import Json.Decode
|
||||
import Json.Decode.Pipeline
|
||||
|
@ -51,6 +49,7 @@ import Search
|
|||
, NixOSChannel
|
||||
, decodeResolvedFlake
|
||||
)
|
||||
import Utils
|
||||
|
||||
|
||||
|
||||
|
@ -185,17 +184,6 @@ viewResultItem :
|
|||
-> Html Msg
|
||||
viewResultItem nixosChannels channel _ show item =
|
||||
let
|
||||
showHtml value =
|
||||
case Html.Parser.run <| String.trim value of
|
||||
Ok [ Html.Parser.Element "rendered-docbook" _ nodes ] ->
|
||||
Just <| Html.Parser.Util.toVirtualDom nodes
|
||||
|
||||
Ok _ ->
|
||||
Nothing
|
||||
|
||||
Err _ ->
|
||||
Nothing
|
||||
|
||||
asPre value =
|
||||
pre [] [ text value ]
|
||||
|
||||
|
@ -210,7 +198,7 @@ viewResultItem nixosChannels channel _ show item =
|
|||
, div [] [ asPreCode item.source.name ]
|
||||
]
|
||||
++ (item.source.description
|
||||
|> Maybe.andThen showHtml
|
||||
|> Maybe.andThen Utils.showHtml
|
||||
|> Maybe.map
|
||||
(\description ->
|
||||
[ div [] [ text "Description" ]
|
||||
|
@ -232,7 +220,7 @@ viewResultItem nixosChannels channel _ show item =
|
|||
|> Maybe.map
|
||||
(\default ->
|
||||
[ div [] [ text "Default" ]
|
||||
, div [] <| Maybe.withDefault [ asPreCode default ] (showHtml default)
|
||||
, div [] <| Maybe.withDefault [ asPreCode default ] (Utils.showHtml default)
|
||||
]
|
||||
)
|
||||
|> Maybe.withDefault []
|
||||
|
@ -241,7 +229,7 @@ viewResultItem nixosChannels channel _ show item =
|
|||
|> Maybe.map
|
||||
(\example ->
|
||||
[ div [] [ text "Example" ]
|
||||
, div [] <| Maybe.withDefault [ asPreCode example ] (showHtml example)
|
||||
, div [] <| Maybe.withDefault [ asPreCode example ] (Utils.showHtml example)
|
||||
]
|
||||
)
|
||||
|> Maybe.withDefault []
|
||||
|
|
|
@ -507,93 +507,93 @@ viewResultItem nixosChannels channel showInstallDetails show item =
|
|||
[ div [ trapClick ]
|
||||
(div []
|
||||
(item.source.longDescription
|
||||
|> Maybe.map (\desc -> [ p [] [ text desc ] ])
|
||||
|> Maybe.andThen Utils.showHtml
|
||||
|> Maybe.withDefault []
|
||||
)
|
||||
:: div []
|
||||
[ h4 []
|
||||
[ text "How to install "
|
||||
, em [] [ text item.source.attr_name ]
|
||||
, text "?"
|
||||
]
|
||||
, ul [ class "nav nav-tabs" ] <|
|
||||
Maybe.withDefault
|
||||
[ li
|
||||
[ classList
|
||||
[ ( "active", List.member showInstallDetails [ Search.Unset, Search.ViaNixShell, Search.FromFlake ] )
|
||||
, ( "pull-right", True )
|
||||
]
|
||||
]
|
||||
[ a
|
||||
[ href "#"
|
||||
, Search.onClickStop <|
|
||||
SearchMsg <|
|
||||
Search.ShowInstallDetails Search.ViaNixShell
|
||||
]
|
||||
[ text "nix-shell" ]
|
||||
]
|
||||
, li
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixOS )
|
||||
, ( "pull-right", True )
|
||||
]
|
||||
]
|
||||
[ a
|
||||
[ href "#"
|
||||
, Search.onClickStop <|
|
||||
SearchMsg <|
|
||||
Search.ShowInstallDetails Search.ViaNixOS
|
||||
]
|
||||
[ text "NixOS Configuration" ]
|
||||
]
|
||||
, li
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixEnv )
|
||||
, ( "pull-right", True )
|
||||
]
|
||||
]
|
||||
[ a
|
||||
[ href "#"
|
||||
, Search.onClickStop <|
|
||||
SearchMsg <|
|
||||
Search.ShowInstallDetails Search.ViaNixEnv
|
||||
]
|
||||
[ text "nix-env" ]
|
||||
]
|
||||
:: div []
|
||||
[ h4 []
|
||||
[ text "How to install "
|
||||
, em [] [ text item.source.attr_name ]
|
||||
, text "?"
|
||||
]
|
||||
<|
|
||||
Maybe.map
|
||||
(\_ ->
|
||||
[ li
|
||||
[ classList
|
||||
[ ( "active", True )
|
||||
, ( "pull-right", True )
|
||||
]
|
||||
]
|
||||
[ a
|
||||
[ href "#"
|
||||
, Search.onClickStop <|
|
||||
SearchMsg <|
|
||||
Search.ShowInstallDetails Search.FromFlake
|
||||
]
|
||||
[ text "Install from flake" ]
|
||||
, ul [ class "nav nav-tabs" ] <|
|
||||
Maybe.withDefault
|
||||
[ li
|
||||
[ classList
|
||||
[ ( "active", List.member showInstallDetails [ Search.Unset, Search.ViaNixShell, Search.FromFlake ] )
|
||||
, ( "pull-right", True )
|
||||
]
|
||||
]
|
||||
)
|
||||
item.source.flakeUrl
|
||||
, div
|
||||
[ class "tab-content" ]
|
||||
<|
|
||||
Maybe.withDefault
|
||||
[ div
|
||||
[ classList
|
||||
[ ( "tab-pane", True )
|
||||
, ( "active", showInstallDetails == Search.ViaNixEnv )
|
||||
[ a
|
||||
[ href "#"
|
||||
, Search.onClickStop <|
|
||||
SearchMsg <|
|
||||
Search.ShowInstallDetails Search.ViaNixShell
|
||||
]
|
||||
[ text "nix-shell" ]
|
||||
]
|
||||
, li
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixOS )
|
||||
, ( "pull-right", True )
|
||||
]
|
||||
]
|
||||
[ a
|
||||
[ href "#"
|
||||
, Search.onClickStop <|
|
||||
SearchMsg <|
|
||||
Search.ShowInstallDetails Search.ViaNixOS
|
||||
]
|
||||
[ text "NixOS Configuration" ]
|
||||
]
|
||||
, li
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixEnv )
|
||||
, ( "pull-right", True )
|
||||
]
|
||||
]
|
||||
[ a
|
||||
[ href "#"
|
||||
, Search.onClickStop <|
|
||||
SearchMsg <|
|
||||
Search.ShowInstallDetails Search.ViaNixEnv
|
||||
]
|
||||
[ text "nix-env" ]
|
||||
]
|
||||
]
|
||||
[ p []
|
||||
[ strong [] [ text "Warning:" ]
|
||||
, text """
|
||||
<|
|
||||
Maybe.map
|
||||
(\_ ->
|
||||
[ li
|
||||
[ classList
|
||||
[ ( "active", True )
|
||||
, ( "pull-right", True )
|
||||
]
|
||||
]
|
||||
[ a
|
||||
[ href "#"
|
||||
, Search.onClickStop <|
|
||||
SearchMsg <|
|
||||
Search.ShowInstallDetails Search.FromFlake
|
||||
]
|
||||
[ text "Install from flake" ]
|
||||
]
|
||||
]
|
||||
)
|
||||
item.source.flakeUrl
|
||||
, div
|
||||
[ class "tab-content" ]
|
||||
<|
|
||||
Maybe.withDefault
|
||||
[ div
|
||||
[ classList
|
||||
[ ( "tab-pane", True )
|
||||
, ( "active", showInstallDetails == Search.ViaNixEnv )
|
||||
]
|
||||
]
|
||||
[ p []
|
||||
[ strong [] [ text "Warning:" ]
|
||||
, text """
|
||||
Using nix-env permanently modifies a
|
||||
local profile of installed packages.
|
||||
This must be cleaned up, updated and
|
||||
|
@ -603,124 +603,124 @@ viewResultItem nixosChannels channel showInstallDetails show item =
|
|||
configuration is recommended
|
||||
instead.
|
||||
"""
|
||||
]
|
||||
]
|
||||
]
|
||||
, div
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixEnv )
|
||||
, div
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixEnv )
|
||||
]
|
||||
, class "tab-pane"
|
||||
]
|
||||
, class "tab-pane"
|
||||
]
|
||||
[ p []
|
||||
[ strong [] [ text "On NixOS:" ] ]
|
||||
]
|
||||
, div
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixEnv )
|
||||
[ p []
|
||||
[ strong [] [ text "On NixOS:" ] ]
|
||||
]
|
||||
, class "tab-pane"
|
||||
, id "package-details-nixpkgs"
|
||||
]
|
||||
[ pre [ class "code-block shell-command" ]
|
||||
[ text "nix-env -iA nixos."
|
||||
, strong [] [ text item.source.attr_name ]
|
||||
, div
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixEnv )
|
||||
]
|
||||
, class "tab-pane"
|
||||
, id "package-details-nixpkgs"
|
||||
]
|
||||
]
|
||||
, div [] [ p [] [] ]
|
||||
, div
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixEnv )
|
||||
[ pre [ class "code-block shell-command" ]
|
||||
[ text "nix-env -iA nixos."
|
||||
, strong [] [ text item.source.attr_name ]
|
||||
]
|
||||
]
|
||||
, class "tab-pane"
|
||||
]
|
||||
[ p []
|
||||
[ strong [] [ text "On Non NixOS:" ] ]
|
||||
]
|
||||
, div
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixEnv )
|
||||
, div [] [ p [] [] ]
|
||||
, div
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixEnv )
|
||||
]
|
||||
, class "tab-pane"
|
||||
]
|
||||
, class "tab-pane"
|
||||
, id "package-details-nixpkgs"
|
||||
]
|
||||
[ pre [ class "code-block shell-command" ]
|
||||
[ text "nix-env -iA nixpkgs."
|
||||
, strong [] [ text item.source.attr_name ]
|
||||
[ p []
|
||||
[ strong [] [ text "On Non NixOS:" ] ]
|
||||
]
|
||||
]
|
||||
, div
|
||||
[ classList
|
||||
[ ( "tab-pane", True )
|
||||
, ( "active", showInstallDetails == Search.ViaNixOS )
|
||||
, div
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixEnv )
|
||||
]
|
||||
, class "tab-pane"
|
||||
, id "package-details-nixpkgs"
|
||||
]
|
||||
]
|
||||
[ p []
|
||||
[ text "Add the following Nix code to your NixOS Configuration, usually located in "
|
||||
, strong [] [ text "/etc/nixos/configuration.nix" ]
|
||||
[ pre [ class "code-block shell-command" ]
|
||||
[ text "nix-env -iA nixpkgs."
|
||||
, strong [] [ text item.source.attr_name ]
|
||||
]
|
||||
]
|
||||
]
|
||||
, div
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixOS )
|
||||
, div
|
||||
[ classList
|
||||
[ ( "tab-pane", True )
|
||||
, ( "active", showInstallDetails == Search.ViaNixOS )
|
||||
]
|
||||
]
|
||||
, class "tab-pane"
|
||||
, id "package-details-nixpkgs"
|
||||
]
|
||||
[ pre [ class "code-block" ]
|
||||
[ text <| " environment.systemPackages = [\n pkgs."
|
||||
, strong [] [ text item.source.attr_name ]
|
||||
, text <| "\n ];"
|
||||
[ p []
|
||||
[ text "Add the following Nix code to your NixOS Configuration, usually located in "
|
||||
, strong [] [ text "/etc/nixos/configuration.nix" ]
|
||||
]
|
||||
]
|
||||
]
|
||||
, div
|
||||
[ classList
|
||||
[ ( "tab-pane", True )
|
||||
, ( "active", List.member showInstallDetails [ Search.Unset, Search.ViaNixShell, Search.FromFlake ] )
|
||||
, div
|
||||
[ classList
|
||||
[ ( "active", showInstallDetails == Search.ViaNixOS )
|
||||
]
|
||||
, class "tab-pane"
|
||||
, id "package-details-nixpkgs"
|
||||
]
|
||||
]
|
||||
[ p []
|
||||
[ text """
|
||||
[ pre [ class "code-block" ]
|
||||
[ text <| " environment.systemPackages = [\n pkgs."
|
||||
, strong [] [ text item.source.attr_name ]
|
||||
, text <| "\n ];"
|
||||
]
|
||||
]
|
||||
, div
|
||||
[ classList
|
||||
[ ( "tab-pane", True )
|
||||
, ( "active", List.member showInstallDetails [ Search.Unset, Search.ViaNixShell, Search.FromFlake ] )
|
||||
]
|
||||
]
|
||||
[ p []
|
||||
[ text """
|
||||
A nix-shell will temporarily modify
|
||||
your $PATH environment variable.
|
||||
This can be used to try a piece of
|
||||
software before deciding to
|
||||
permanently install it.
|
||||
"""
|
||||
]
|
||||
]
|
||||
, div
|
||||
[ classList
|
||||
[ ( "tab-pane", True )
|
||||
, ( "active", List.member showInstallDetails [ Search.Unset, Search.ViaNixShell, Search.FromFlake ] )
|
||||
]
|
||||
]
|
||||
[ pre [ class "code-block shell-command" ]
|
||||
[ text "nix-shell -p "
|
||||
, strong [] [ text item.source.attr_name ]
|
||||
]
|
||||
]
|
||||
]
|
||||
<|
|
||||
Maybe.map
|
||||
(\url ->
|
||||
[ div
|
||||
[ classList
|
||||
[ ( "tab-pane", True )
|
||||
, ( "active", True )
|
||||
]
|
||||
]
|
||||
[ pre [ class "code-block shell-command" ]
|
||||
[ text "nix build "
|
||||
, strong [] [ text url ]
|
||||
, text "#"
|
||||
, em [] [ text item.source.attr_name ]
|
||||
]
|
||||
]
|
||||
]
|
||||
)
|
||||
, div
|
||||
[ classList
|
||||
[ ( "tab-pane", True )
|
||||
, ( "active", List.member showInstallDetails [ Search.Unset, Search.ViaNixShell, Search.FromFlake ] )
|
||||
]
|
||||
]
|
||||
[ pre [ class "code-block shell-command" ]
|
||||
[ text "nix-shell -p "
|
||||
, strong [] [ text item.source.attr_name ]
|
||||
]
|
||||
]
|
||||
]
|
||||
<|
|
||||
Maybe.map Tuple.first item.source.flakeUrl
|
||||
]
|
||||
Maybe.map
|
||||
(\url ->
|
||||
[ div
|
||||
[ classList
|
||||
[ ( "tab-pane", True )
|
||||
, ( "active", True )
|
||||
]
|
||||
]
|
||||
[ pre [ class "code-block shell-command" ]
|
||||
[ text "nix build "
|
||||
, strong [] [ text url ]
|
||||
, text "#"
|
||||
, em [] [ text item.source.attr_name ]
|
||||
]
|
||||
]
|
||||
]
|
||||
)
|
||||
<|
|
||||
Maybe.map Tuple.first item.source.flakeUrl
|
||||
]
|
||||
:: maintainersAndPlatforms
|
||||
)
|
||||
]
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
module Utils exposing (toggleList)
|
||||
module Utils exposing
|
||||
( showHtml
|
||||
, toggleList
|
||||
)
|
||||
|
||||
import Html.Parser
|
||||
import Html.Parser.Util
|
||||
|
||||
|
||||
toggleList :
|
||||
|
@ -11,3 +17,12 @@ toggleList list item =
|
|||
|
||||
else
|
||||
List.append list [ item ]
|
||||
|
||||
|
||||
showHtml value =
|
||||
case Html.Parser.run <| String.trim value of
|
||||
Ok [ Html.Parser.Element "rendered-html" _ nodes ] ->
|
||||
Just <| Html.Parser.Util.toVirtualDom nodes
|
||||
|
||||
_ ->
|
||||
Nothing
|
||||
|
|
Loading…
Reference in a new issue