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",
|
"serde_path_to_error",
|
||||||
"sha2",
|
"sha2",
|
||||||
"structopt",
|
"structopt",
|
||||||
"tempfile",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
|
@ -866,9 +865,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pandoc"
|
name = "pandoc"
|
||||||
version = "0.8.8"
|
version = "0.8.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0eac785b7de8de25c5ec48b3a9df1be552de03906f99145ed6d7da3d696c0dbb"
|
checksum = "2eb8469d27ed9fd7925629076a3675fea964c3f44c49662bdf549a8b7ddf0820"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
]
|
]
|
||||||
|
|
|
@ -18,13 +18,12 @@ structopt = "0.3"
|
||||||
command-run = "0.13"
|
command-run = "0.13"
|
||||||
env_logger = "0.9"
|
env_logger = "0.9"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
tempfile = "3"
|
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
fancy-regex = "0.6"
|
fancy-regex = "0.6"
|
||||||
tokio = { version = "*", features = ["full"] }
|
tokio = { version = "*", features = ["full"] }
|
||||||
reqwest = { version = "0.11", features = ["json", "blocking"] }
|
reqwest = { version = "0.11", features = ["json", "blocking"] }
|
||||||
sha2 = "0.9"
|
sha2 = "0.9"
|
||||||
pandoc = "0.8"
|
pandoc = "0.8.10"
|
||||||
semver = "1.0"
|
semver = "1.0"
|
||||||
|
|
||||||
elasticsearch = {git = "https://github.com/elastic/elasticsearch-rs", features = ["rustls-tls"], optional = true}
|
elasticsearch = {git = "https://github.com/elastic/elasticsearch-rs", features = ["rustls-tls"], optional = true}
|
||||||
|
|
|
@ -19,6 +19,7 @@ let
|
||||||
readPackages = system: drvs: lib.mapAttrsToList (
|
readPackages = system: drvs: lib.mapAttrsToList (
|
||||||
attribute_name: drv: (
|
attribute_name: drv: (
|
||||||
{
|
{
|
||||||
|
entry_type = "package";
|
||||||
attribute_name = attribute_name;
|
attribute_name = attribute_name;
|
||||||
system = system;
|
system = system;
|
||||||
name = drv.name;
|
name = drv.name;
|
||||||
|
@ -35,6 +36,7 @@ let
|
||||||
readApps = system: apps: lib.mapAttrsToList (
|
readApps = system: apps: lib.mapAttrsToList (
|
||||||
attribute_name: app: (
|
attribute_name: app: (
|
||||||
{
|
{
|
||||||
|
entry_type = "app";
|
||||||
attribute_name = attribute_name;
|
attribute_name = attribute_name;
|
||||||
system = system;
|
system = system;
|
||||||
}
|
}
|
||||||
|
@ -86,6 +88,7 @@ let
|
||||||
x;
|
x;
|
||||||
in
|
in
|
||||||
opt
|
opt
|
||||||
|
// { entry_type = "option"; }
|
||||||
// applyOnAttr "default" substFunction
|
// applyOnAttr "default" substFunction
|
||||||
// applyOnAttr "example" substFunction # (_: { __type = "function"; })
|
// applyOnAttr "example" substFunction # (_: { __type = "function"; })
|
||||||
// applyOnAttr "type" substFunction
|
// applyOnAttr "type" substFunction
|
|
@ -23,16 +23,17 @@ pkgs.rustPlatform.buildRustPackage rec {
|
||||||
|
|
||||||
checkInputs = with pkgs; [ pandoc ];
|
checkInputs = with pkgs; [ pandoc ];
|
||||||
|
|
||||||
|
ROOTDIR = builtins.placeholder "out";
|
||||||
NIXPKGS_PANDOC_FILTERS_PATH = "${pkgs.path + "/doc/build-aux/pandoc-filters"}";
|
NIXPKGS_PANDOC_FILTERS_PATH = "${pkgs.path + "/doc/build-aux/pandoc-filters"}";
|
||||||
|
|
||||||
checkFlags = [
|
checkFlags = [
|
||||||
"--skip elastic::tests"
|
"--skip elastic::tests"
|
||||||
"--skip nix_gc::tests"
|
|
||||||
];
|
];
|
||||||
|
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
|
cp -rt "$out" assets
|
||||||
|
|
||||||
wrapProgram $out/bin/flake-info \
|
wrapProgram $out/bin/flake-info \
|
||||||
--set NIXPKGS_PANDOC_FILTERS_PATH "${NIXPKGS_PANDOC_FILTERS_PATH}" \
|
|
||||||
--set NIXOS_CHANNELS '${builtins.toJSON nixosChannels}' \
|
--set NIXOS_CHANNELS '${builtins.toJSON nixosChannels}' \
|
||||||
--prefix PATH : ${pkgs.pandoc}/bin
|
--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_attrs::get_derivation_info;
|
||||||
pub use nix_flake_info::get_flake_info;
|
pub use nix_flake_info::get_flake_info;
|
||||||
pub use nixpkgs_info::{get_nixpkgs_info, get_nixpkgs_options};
|
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 command_run::{Command, LogTo};
|
||||||
use serde_json::Deserializer;
|
use serde_json::Deserializer;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Write;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
const SCRIPT: &str = include_str!("flake_info.nix");
|
|
||||||
const ARGS: [&str; 4] = [
|
const ARGS: [&str; 4] = [
|
||||||
"eval",
|
"eval",
|
||||||
"--json",
|
"--json",
|
||||||
|
@ -23,12 +20,8 @@ pub fn get_derivation_info<T: AsRef<str> + Display>(
|
||||||
temp_store: bool,
|
temp_store: bool,
|
||||||
extra: &[String],
|
extra: &[String],
|
||||||
) -> Result<Vec<FlakeEntry>> {
|
) -> 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());
|
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_arg_pair("-I", "nixpkgs=channel:nixpkgs-unstable");
|
||||||
command.add_args(["--override-flake", "input-flake", flake_ref.as_ref()].iter());
|
command.add_args(["--override-flake", "input-flake", flake_ref.as_ref()].iter());
|
||||||
command.add_args(["--argstr", "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 anyhow::{Context, Result};
|
||||||
use serde_json::Deserializer;
|
use serde_json::Deserializer;
|
||||||
use std::io::Write;
|
use std::{collections::HashMap, fmt::Display};
|
||||||
use std::{collections::HashMap, fmt::Display, fs::File};
|
|
||||||
|
|
||||||
use command_run::{Command, LogTo};
|
use command_run::{Command, LogTo};
|
||||||
use log::error;
|
use log::error;
|
||||||
|
|
||||||
use crate::data::import::{NixOption, NixpkgsEntry, Package};
|
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>> {
|
pub fn get_nixpkgs_info<T: AsRef<str> + Display>(nixpkgs_channel: T) -> Result<Vec<NixpkgsEntry>> {
|
||||||
let mut command = Command::new("nix-env");
|
let mut command = Command::new("nix-env");
|
||||||
command.add_args(&[
|
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>(
|
pub fn get_nixpkgs_options<T: AsRef<str> + Display>(
|
||||||
nixpkgs_channel: T,
|
nixpkgs_channel: T,
|
||||||
) -> Result<Vec<NixpkgsEntry>> {
|
) -> Result<Vec<NixpkgsEntry>> {
|
||||||
let script_dir = tempfile::tempdir()?;
|
let mut command = Command::with_args("nix", &["eval", "--json"]);
|
||||||
let script_path = script_dir.path().join("flake_info.nix");
|
command.add_arg_pair("-f", super::EXTRACT_SCRIPT.clone());
|
||||||
writeln!(File::create(&script_path)?, "{}", FLAKE_INFO_SCRIPT)?;
|
command.add_arg_pair("-I", format!("nixpkgs={}", nixpkgs_channel.as_ref()));
|
||||||
|
command.add_arg("nixos-options");
|
||||||
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",
|
|
||||||
]);
|
|
||||||
|
|
||||||
command.enable_capture();
|
command.enable_capture();
|
||||||
command.log_to = LogTo::Log;
|
command.log_to = LogTo::Log;
|
||||||
|
|
|
@ -6,26 +6,14 @@ use std::{
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
|
||||||
import::{DocValue, ModulePath},
|
|
||||||
pandoc::PandocExt,
|
|
||||||
};
|
|
||||||
use crate::data::import::NixOption;
|
|
||||||
use anyhow::Context;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
import,
|
import::{self, DocString, DocValue, ModulePath, NixOption},
|
||||||
|
pandoc::PandocExt,
|
||||||
system::System,
|
system::System,
|
||||||
utility::{AttributeQuery, Flatten, OneOrMany, Reverse},
|
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;
|
type Flake = super::Flake;
|
||||||
|
|
||||||
|
@ -107,8 +95,7 @@ pub enum Derivation {
|
||||||
option_name_query: AttributeQuery,
|
option_name_query: AttributeQuery,
|
||||||
option_name_query_reverse: Reverse<AttributeQuery>,
|
option_name_query_reverse: Reverse<AttributeQuery>,
|
||||||
|
|
||||||
option_description: Option<String>,
|
option_description: Option<DocString>,
|
||||||
option_description_reverse: Option<Reverse<String>>,
|
|
||||||
|
|
||||||
option_type: Option<String>,
|
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_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
|
let package_license_set: Vec<String> = package_license
|
||||||
.iter()
|
.iter()
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -215,7 +207,7 @@ impl TryFrom<import::NixpkgsEntry> for Derivation {
|
||||||
|
|
||||||
let package_attr_set_reverse = Reverse(package_attr_set.clone());
|
let package_attr_set_reverse = Reverse(package_attr_set.clone());
|
||||||
|
|
||||||
let package_license: Vec<_> = package
|
let package_license: Vec<License> = package
|
||||||
.meta
|
.meta
|
||||||
.license
|
.license
|
||||||
.map(OneOrMany::into_list)
|
.map(OneOrMany::into_list)
|
||||||
|
@ -242,6 +234,12 @@ impl TryFrom<import::NixpkgsEntry> for Derivation {
|
||||||
.flat_map(|m| m.name.to_owned())
|
.flat_map(|m| m.name.to_owned())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let long_description = package
|
||||||
|
.meta
|
||||||
|
.long_description
|
||||||
|
.map(|s| s.render_markdown())
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
let position: Option<String> = package.meta.position.map(|p| {
|
let position: Option<String> = package.meta.position.map(|p| {
|
||||||
if p.starts_with("/nix/store") {
|
if p.starts_with("/nix/store") {
|
||||||
p.split("/").skip(4).collect::<Vec<&str>>().join("/")
|
p.split("/").skip(4).collect::<Vec<&str>>().join("/")
|
||||||
|
@ -273,8 +271,8 @@ impl TryFrom<import::NixpkgsEntry> for Derivation {
|
||||||
package_maintainers_set,
|
package_maintainers_set,
|
||||||
package_description: package.meta.description.clone(),
|
package_description: package.meta.description.clone(),
|
||||||
package_description_reverse: package.meta.description.map(Reverse),
|
package_description_reverse: package.meta.description.map(Reverse),
|
||||||
package_longDescription: package.meta.long_description.clone(),
|
package_longDescription: long_description.clone(),
|
||||||
package_longDescription_reverse: package.meta.long_description.map(Reverse),
|
package_longDescription_reverse: long_description.map(Reverse),
|
||||||
package_hydra: (),
|
package_hydra: (),
|
||||||
package_system: package.system,
|
package_system: package.system,
|
||||||
package_homepage: package
|
package_homepage: package
|
||||||
|
@ -303,32 +301,13 @@ impl TryFrom<import::NixOption> for Derivation {
|
||||||
flake,
|
flake,
|
||||||
}: import::NixOption,
|
}: import::NixOption,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> 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 {
|
Ok(Derivation::Option {
|
||||||
option_source: declarations.get(0).map(Clone::clone),
|
option_source: declarations.get(0).map(Clone::clone),
|
||||||
option_name: name.clone(),
|
option_name: name.clone(),
|
||||||
option_name_reverse: Reverse(name.clone()),
|
option_name_reverse: Reverse(name.clone()),
|
||||||
option_description: description.clone(),
|
option_description: description,
|
||||||
option_description_reverse: description.map(Reverse),
|
option_default: default,
|
||||||
option_default,
|
option_example: example,
|
||||||
option_example,
|
|
||||||
option_flake: flake,
|
option_flake: flake,
|
||||||
option_type,
|
option_type,
|
||||||
option_name_query: AttributeQuery::new(&name),
|
option_name_query: AttributeQuery::new(&name),
|
||||||
|
|
|
@ -16,7 +16,7 @@ use super::utility::{Flatten, OneOrMany};
|
||||||
|
|
||||||
/// Holds information about a specific derivation
|
/// Holds information about a specific derivation
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(tag = "entry_type", rename_all = "lowercase")]
|
||||||
pub enum FlakeEntry {
|
pub enum FlakeEntry {
|
||||||
/// A package as it may be defined in a flake
|
/// A package as it may be defined in a flake
|
||||||
///
|
///
|
||||||
|
@ -31,8 +31,7 @@ pub enum FlakeEntry {
|
||||||
outputs: Vec<String>,
|
outputs: Vec<String>,
|
||||||
default_output: String,
|
default_output: String,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
#[serde(deserialize_with = "string_or_struct", default)]
|
license: Option<OneOrMany<StringOrStruct<License>>>,
|
||||||
license: License,
|
|
||||||
},
|
},
|
||||||
/// An "application" that can be called using nix run <..>
|
/// An "application" that can be called using nix run <..>
|
||||||
App {
|
App {
|
||||||
|
@ -52,7 +51,7 @@ pub struct NixOption {
|
||||||
/// Location of the defining module(s)
|
/// Location of the defining module(s)
|
||||||
pub declarations: Vec<String>,
|
pub declarations: Vec<String>,
|
||||||
|
|
||||||
pub description: Option<String>,
|
pub description: Option<DocString>,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
|
@ -79,6 +78,20 @@ pub enum ModulePath {
|
||||||
NamedModule((String, String)),
|
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)]
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum DocValue {
|
pub enum DocValue {
|
||||||
|
@ -89,12 +102,34 @@ pub enum DocValue {
|
||||||
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||||
#[serde(tag = "_type", content = "text")]
|
#[serde(tag = "_type", content = "text")]
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
#[serde(rename = "literalExpression")]
|
#[serde(rename = "literalExpression", alias = "literalExample")]
|
||||||
LiteralExpression(String),
|
LiteralExpression(String),
|
||||||
#[serde(rename = "literalExample")]
|
|
||||||
LiteralExample(String),
|
|
||||||
#[serde(rename = "literalDocBook")]
|
#[serde(rename = "literalDocBook")]
|
||||||
LiteralDocBook(String),
|
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 {
|
impl Serialize for DocValue {
|
||||||
|
@ -103,14 +138,18 @@ impl Serialize for DocValue {
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
DocValue::Literal(Literal::LiteralExample(s) | Literal::LiteralExpression(s)) => {
|
DocValue::Literal(Literal::LiteralExpression(s)) => serializer.serialize_str(&s),
|
||||||
return 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)) => {
|
DocValue::Literal(Literal::LiteralMarkdown(md)) => {
|
||||||
return serializer.serialize_str(&doc_book.render().unwrap_or_else(|e| {
|
serializer.serialize_str(&md.render_markdown().unwrap_or_else(|e| {
|
||||||
warn!("Could not render docbook content: {}", e);
|
warn!("Could not render Markdown content: {}", e);
|
||||||
doc_book.to_owned()
|
md.to_owned()
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
DocValue::Value(v) => serializer.serialize_str(&print_value(v.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 lazy_static::lazy_static;
|
||||||
use pandoc::{
|
use std::path::{Path, PathBuf};
|
||||||
InputFormat, InputKind, OutputFormat, OutputKind, PandocError, PandocOption, PandocOutput,
|
|
||||||
};
|
|
||||||
|
|
||||||
const XREF_FILTER: &str = include_str!("fix-xrefs.lua");
|
use pandoc::*;
|
||||||
|
|
||||||
|
const FILTERS_PATH: &str = env!("NIXPKGS_PANDOC_FILTERS_PATH");
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref FILTERS_PATH: PathBuf = std::env::var("NIXPKGS_PANDOC_FILTERS_PATH")
|
static ref DOCBOOK_ROLES_FILTER: PathBuf =
|
||||||
.unwrap_or("".into())
|
Path::new(FILTERS_PATH).join("docbook-reader/citerefentry-to-rst-role.lua");
|
||||||
.into();
|
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 {
|
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 {
|
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("<") {
|
if !self.as_ref().contains("<") {
|
||||||
return Ok(format!(
|
return Ok(format!(
|
||||||
"<rendered-docbook>{}</rendered-docbook>",
|
"<rendered-html><p>{}</p></rendered-html>",
|
||||||
self.as_ref()
|
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!(
|
let wrapper_xml = format!(
|
||||||
"
|
"
|
||||||
<xml xmlns:xlink=\"http://www.w3.org/1999/xlink\">
|
<xml xmlns:xlink=\"http://www.w3.org/1999/xlink\">
|
||||||
|
@ -52,19 +38,52 @@ impl<T: AsRef<str>> PandocExt for T {
|
||||||
self.as_ref()
|
self.as_ref()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut pandoc = pandoc::new();
|
||||||
pandoc.set_input(InputKind::Pipe(wrapper_xml));
|
pandoc.set_input(InputKind::Pipe(wrapper_xml));
|
||||||
pandoc.set_input_format(InputFormat::DocBook, Vec::new());
|
pandoc.set_input_format(InputFormat::DocBook, Vec::new());
|
||||||
pandoc.set_output(OutputKind::Pipe);
|
pandoc.set_output(OutputKind::Pipe);
|
||||||
pandoc.set_output_format(OutputFormat::Html, Vec::new());
|
pandoc.set_output_format(OutputFormat::Html, Vec::new());
|
||||||
pandoc.add_options(&[
|
pandoc.add_options(&[
|
||||||
PandocOption::LuaFilter(citeref_filter),
|
PandocOption::LuaFilter(DOCBOOK_ROLES_FILTER.clone()),
|
||||||
PandocOption::LuaFilter(man_filter),
|
PandocOption::LuaFilter(MANPAGE_LINK_FILTER.clone()),
|
||||||
PandocOption::LuaFilter(xref_filter),
|
PandocOption::LuaFilter(XREF_FILTER.clone()),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
pandoc.execute().map(|result| match result {
|
pandoc.execute().map(|result| match result {
|
||||||
PandocOutput::ToBuffer(description) => {
|
PandocOutput::ToBuffer(html) => {
|
||||||
format!("<rendered-docbook>{}</rendered-docbook>", description)
|
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!(),
|
_ => unreachable!(),
|
||||||
})
|
})
|
||||||
|
|
|
@ -174,11 +174,6 @@ lazy_static! {
|
||||||
"analyzer": "english",
|
"analyzer": "english",
|
||||||
"fields": {"edge": {"type": "text", "analyzer": "edge"}},
|
"fields": {"edge": {"type": "text", "analyzer": "edge"}},
|
||||||
},
|
},
|
||||||
"option_description_reverse": {
|
|
||||||
"type": "text",
|
|
||||||
"analyzer": "english",
|
|
||||||
"fields": {"edge": {"type": "text", "analyzer": "edge"}},
|
|
||||||
},
|
|
||||||
"option_type": {"type": "keyword"},
|
"option_type": {"type": "keyword"},
|
||||||
"option_default": {"type": "text"},
|
"option_default": {"type": "text"},
|
||||||
"option_example": {"type": "text"},
|
"option_example": {"type": "text"},
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use data::{import::Kind, Export, Flake, Source};
|
use data::{import::Kind, Export, Flake, Source};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
pub mod data;
|
pub mod data;
|
||||||
|
@ -12,6 +14,11 @@ pub mod elastic;
|
||||||
pub use commands::get_flake_info;
|
pub use commands::get_flake_info;
|
||||||
use log::trace;
|
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(
|
pub fn process_flake(
|
||||||
source: &Source,
|
source: &Source,
|
||||||
kind: &data::import::Kind,
|
kind: &data::import::Kind,
|
||||||
|
|
|
@ -39,8 +39,6 @@ import Html.Events
|
||||||
exposing
|
exposing
|
||||||
( onClick
|
( onClick
|
||||||
)
|
)
|
||||||
import Html.Parser
|
|
||||||
import Html.Parser.Util
|
|
||||||
import Http exposing (Body)
|
import Http exposing (Body)
|
||||||
import Json.Decode
|
import Json.Decode
|
||||||
import Json.Decode.Pipeline
|
import Json.Decode.Pipeline
|
||||||
|
@ -51,6 +49,7 @@ import Search
|
||||||
, NixOSChannel
|
, NixOSChannel
|
||||||
, decodeResolvedFlake
|
, decodeResolvedFlake
|
||||||
)
|
)
|
||||||
|
import Utils
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -185,17 +184,6 @@ viewResultItem :
|
||||||
-> Html Msg
|
-> Html Msg
|
||||||
viewResultItem nixosChannels channel _ show item =
|
viewResultItem nixosChannels channel _ show item =
|
||||||
let
|
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 =
|
asPre value =
|
||||||
pre [] [ text value ]
|
pre [] [ text value ]
|
||||||
|
|
||||||
|
@ -210,7 +198,7 @@ viewResultItem nixosChannels channel _ show item =
|
||||||
, div [] [ asPreCode item.source.name ]
|
, div [] [ asPreCode item.source.name ]
|
||||||
]
|
]
|
||||||
++ (item.source.description
|
++ (item.source.description
|
||||||
|> Maybe.andThen showHtml
|
|> Maybe.andThen Utils.showHtml
|
||||||
|> Maybe.map
|
|> Maybe.map
|
||||||
(\description ->
|
(\description ->
|
||||||
[ div [] [ text "Description" ]
|
[ div [] [ text "Description" ]
|
||||||
|
@ -232,7 +220,7 @@ viewResultItem nixosChannels channel _ show item =
|
||||||
|> Maybe.map
|
|> Maybe.map
|
||||||
(\default ->
|
(\default ->
|
||||||
[ div [] [ text "Default" ]
|
[ div [] [ text "Default" ]
|
||||||
, div [] <| Maybe.withDefault [ asPreCode default ] (showHtml default)
|
, div [] <| Maybe.withDefault [ asPreCode default ] (Utils.showHtml default)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|> Maybe.withDefault []
|
|> Maybe.withDefault []
|
||||||
|
@ -241,7 +229,7 @@ viewResultItem nixosChannels channel _ show item =
|
||||||
|> Maybe.map
|
|> Maybe.map
|
||||||
(\example ->
|
(\example ->
|
||||||
[ div [] [ text "Example" ]
|
[ div [] [ text "Example" ]
|
||||||
, div [] <| Maybe.withDefault [ asPreCode example ] (showHtml example)
|
, div [] <| Maybe.withDefault [ asPreCode example ] (Utils.showHtml example)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|> Maybe.withDefault []
|
|> Maybe.withDefault []
|
||||||
|
|
|
@ -507,7 +507,7 @@ viewResultItem nixosChannels channel showInstallDetails show item =
|
||||||
[ div [ trapClick ]
|
[ div [ trapClick ]
|
||||||
(div []
|
(div []
|
||||||
(item.source.longDescription
|
(item.source.longDescription
|
||||||
|> Maybe.map (\desc -> [ p [] [ text desc ] ])
|
|> Maybe.andThen Utils.showHtml
|
||||||
|> Maybe.withDefault []
|
|> Maybe.withDefault []
|
||||||
)
|
)
|
||||||
:: div []
|
:: div []
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
module Utils exposing (toggleList)
|
module Utils exposing
|
||||||
|
( showHtml
|
||||||
|
, toggleList
|
||||||
|
)
|
||||||
|
|
||||||
|
import Html.Parser
|
||||||
|
import Html.Parser.Util
|
||||||
|
|
||||||
|
|
||||||
toggleList :
|
toggleList :
|
||||||
|
@ -11,3 +17,12 @@ toggleList list item =
|
||||||
|
|
||||||
else
|
else
|
||||||
List.append list [ item ]
|
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