🚚 Gran actualización de Paquetes a Extensiones

This commit is contained in:
Manuel Cillero 2025-01-15 17:46:46 +01:00
parent efaa231481
commit 332d8c1ad9
443 changed files with 1123 additions and 444 deletions

View file

@ -0,0 +1,61 @@
//! Opciones de configuración.
//!
//! Ejemplo:
//!
//! ```toml
//! [hljs]
//! mode = "core"
//! theme = "zenburn"
//! tabsize = 8
//! ```
//!
//! Uso:
//!
//! ```rust#ignore
//! use pagetop_hljs::config;
//!
//! assert_eq!(config::SETTINGS.hljs.theme, "zenburn");
//! ```
//!
//! Consulta [`pagetop::config`] para aprender cómo `PageTop` lee los archivos de opciones y aplica
//! los valores de configuración.
use pagetop::prelude::*;
use crate::mode::HljsMode;
use crate::theme::HljsTheme;
use serde::Deserialize;
include_config!(SETTINGS: Settings => [
// [hljs]
"hljs.mode" => "core",
"hljs.theme" => "default",
"hljs.tabsize" => 4,
]);
#[derive(Debug, Deserialize)]
/// Opciones de configuración para la sección [`[hljs]`](Hljs) (ver [`SETTINGS`]).
pub struct Settings {
pub hljs: Hljs,
}
#[derive(Debug, Deserialize)]
/// Sección `[hljs]` de la configuración.
///
/// Ver [`Settings`].
pub struct Hljs {
/// Usa ***core*** para importar una librería mínima y cargar solo los lenguajes añadidos vía
/// [`add_hljs_language()`](crate::context::HljsContext::add_hljs_language). Por otro lado, usa
/// ***common*** para importar una librería extendida con los 40 lenguajes más habituales según
/// [`HljsLang`](crate::lang::HljsLang). Ten en cuenta que al usar la librería *common* te
/// limitas a los lenguajes que vienen precargados.
/// Valor por defecto: *"core"*
pub mode: HljsMode,
/// Tema por defecto en formato *kebab-case* para mostrar los fragmentos de código en las
/// páginas web (ver [`HljsTheme`]).
/// Valor por defecto: *"default"*
pub theme: HljsTheme,
/// Número de espacios para el carácter tabulador.
/// Valor por defecto: *4*
pub tabsize: usize,
}

View file

@ -0,0 +1,96 @@
use pagetop::prelude::*;
use crate::config;
use crate::lang::HljsLang;
use crate::mode::HljsMode;
use crate::theme::HljsTheme;
use std::collections::HashSet;
// Parámetros para el contexto.
const PARAM_HLJS_ENABLED: &str = "hljs.enabled";
const PARAM_HLJS_MODE: &str = "hljs.mode";
const PARAM_HLJS_LANGS: &str = "hljs.langs";
const PARAM_HLJS_THEME: &str = "hljs.theme";
/// Extiende el contexto de renderizado con funcionalidades de HighlightJS.
pub trait HljsContext {
/// Habilita el resaltado de sintaxis en el contexto actual.
fn enable_hljs(&mut self);
/// Deshabilita el resaltado de sintaxis en el contexto actual.
fn disable_hljs(&mut self);
/// Fuerza el uso del modo ***core*** o ***common*** de *highlight.js* en el contexto actual,
/// ignorando [`config::SETTINGS.hljs.mode`](crate::config::Hljs#structfield.mode) de las
/// opciones de configuración.
fn force_hljs_mode(&mut self, mode: &HljsMode);
/// Añade un nuevo lenguaje al contexto actual para el resaltado de fragmentos de código. Se
/// requiere al menos un lenguaje para cargar la librería *highlight.js*. Recuerda que cada
/// componente [`Snippet`](crate::snippet::HljsSnippet) añade automáticamente el lenguaje que
/// necesita. Solo aplica cuando el contexto está configurado en el modo ***core***.
fn add_hljs_language(&mut self, language: &HljsLang);
/// Cambia el tema del contexto actual para mostrar los fragmentos de código. Ten en cuenta que
/// *highlight.js* utilizará el mismo tema para todos los framentos en este contexto.
fn set_hljs_theme(&mut self, theme: &HljsTheme);
fn is_hljs_enabled(&self) -> bool;
fn hljs_mode(&self) -> HljsMode;
fn hljs_languages(&self) -> Option<HashSet<String>>;
fn hljs_theme(&self) -> HljsTheme;
}
impl HljsContext for Context {
fn enable_hljs(&mut self) {
self.alter_param::<bool>(PARAM_HLJS_ENABLED, &true);
}
fn disable_hljs(&mut self) {
self.alter_param::<bool>(PARAM_HLJS_ENABLED, &false);
}
fn force_hljs_mode(&mut self, mode: &HljsMode) {
self.alter_param::<HljsMode>(PARAM_HLJS_MODE, mode);
}
fn add_hljs_language(&mut self, language: &HljsLang) {
let languages = match self.get_param::<String>(PARAM_HLJS_LANGS) {
Ok(previous) => join_string!(previous, ";", language.to_string()),
_ => language.to_string(),
};
self.alter_param::<String>(PARAM_HLJS_LANGS, &languages);
}
fn set_hljs_theme(&mut self, theme: &HljsTheme) {
self.alter_param::<String>(PARAM_HLJS_THEME, &theme.to_string());
}
// HljsContext GETTERS.
fn is_hljs_enabled(&self) -> bool {
self.get_param::<bool>(PARAM_HLJS_ENABLED).unwrap_or(true)
}
fn hljs_mode(&self) -> HljsMode {
self.get_param::<HljsMode>(PARAM_HLJS_MODE)
.unwrap_or(config::SETTINGS.hljs.mode)
}
fn hljs_languages(&self) -> Option<HashSet<String>> {
if let Ok(languages) = self.get_param::<String>(PARAM_HLJS_LANGS) {
let set: HashSet<String> = languages.split(';').map(|s| s.to_string()).collect();
return Some(set);
}
None
}
fn hljs_theme(&self) -> HljsTheme {
self.get_param::<HljsTheme>(PARAM_HLJS_THEME)
.unwrap_or(config::SETTINGS.hljs.theme)
}
}

View file

@ -0,0 +1,246 @@
use pagetop::prelude::*;
use std::collections::HashMap;
use std::str::FromStr;
use std::sync::LazyLock;
use std::fmt;
/// Supported coding languages.
///
/// Languages are represented by *PascalCase* enums within the code and are mapped to corresponding
/// [highlight.js](https://highlightjs.org/) language names.
///
/// ```rust#ignore
/// use pagetop_hljs::HljsLang;
///
/// assert_eq!(HljsLang::CoffeeScript.to_string(), "coffeescript".to_string());
/// ```
#[derive(AutoDefault, Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum HljsLang {
// Common languages.
Bash,
C,
Cpp,
Csharp,
CSS,
Diff,
Go,
GraphQL,
HTML,
INI,
Java,
JavaScript,
JSON,
Kotlin,
Less,
Lua,
Makefile,
Markdown,
ObjectiveC,
Perl,
PHP,
PHPTemplate,
#[default]
Plaintext,
Python,
PythonREPL,
R,
Ruby,
Rust,
SCSS,
ShellSession,
SQL,
Swift,
TOML,
TypeScript,
VisualBasicNET,
WebAssembly,
XML,
/// Enum variants for languages ranging from `Bash` to `YAML` are all preloaded in the
/// ***common*** mode. To include additional languages, use the default ***core*** mode.
///
/// See [`config::SETTINGS.hljs.mode`](crate::config::Hljs#structfield.mode).
YAML,
// Additional languages.
ActionScript,
Ada,
Apache,
AppleScript,
Arduino,
ARMAssembly,
AsciiDoc,
AspectJ,
AutoHotkey,
AVRAssembly,
Awk,
BASIC,
Clojure,
ClojureREPL,
CMake,
CoffeeScript,
Crystal,
D,
Dart,
Delphy,
Django,
DNSZone,
Dockerfile,
DOS,
Elixir,
Elm,
ERB,
Erlang,
ErlangREPL,
Fortran,
Fsharp,
Handlebars,
Haskell,
HTTP,
Julia,
JuliaREPL,
LaTeX,
Lisp,
LLVMIR,
Matlab,
Nginx,
NodeREPL,
Ocaml,
PostgreSQL,
PowerShell,
Prolog,
Properties,
Scala,
Scheme,
Scilab,
Smalltalk,
Tcl,
Twig,
VBScript,
X86Asm,
}
static HLJS_LANGS: LazyLock<HashMap<HljsLang, &'static str>> = LazyLock::new(|| {
use HljsLang::*;
hm![
// Common languages.
Bash => "bash",
C => "c",
Cpp => "cpp",
Csharp => "csharp",
CSS => "css",
Diff => "diff",
Go => "go",
GraphQL => "graphql",
HTML => "html,xml",
INI => "ini",
Java => "java",
JavaScript => "javascript",
JSON => "json",
Kotlin => "kotlin",
Less => "less",
Lua => "lua",
Makefile => "makefile",
Markdown => "markdown",
ObjectiveC => "objectivec",
Perl => "perl",
PHP => "php",
PHPTemplate => "php-template",
Plaintext => "plaintext",
Python => "python",
PythonREPL => "python-repl",
R => "r",
Ruby => "ruby",
Rust => "rust",
SCSS => "scss",
ShellSession => "shell",
SQL => "sql",
Swift => "swift",
TOML => "toml,ini",
TypeScript => "typescript",
VisualBasicNET => "vbnet",
WebAssembly => "wasm",
XML => "xml",
YAML => "yaml",
// Additional languages.
ActionScript => "actionscript",
Ada => "ada",
Apache => "apache",
AppleScript => "applescript",
Arduino => "arduino",
ARMAssembly => "armasm",
AsciiDoc => "asciidoc",
AspectJ => "aspectj",
AutoHotkey => "autohotkey",
AVRAssembly => "avrasm",
Awk => "awk",
BASIC => "basic",
Clojure => "clojure",
ClojureREPL => "clojure-repl",
CMake => "cmake",
CoffeeScript => "coffeescript",
Crystal => "crystal",
D => "d",
Dart => "dart",
Delphy => "delphy",
Django => "django",
DNSZone => "dns",
Dockerfile => "dockerfile",
DOS => "dos",
Elixir => "elixir",
Elm => "elm",
ERB => "erb",
Erlang => "erlang",
ErlangREPL => "erlang-repl",
Fortran => "fortran",
Fsharp => "fsharp",
Handlebars => "handlebars",
Haskell => "haskell",
HTTP => "http",
Julia => "julia",
JuliaREPL => "julia-repl",
LaTeX => "latex",
Lisp => "lisp",
LLVMIR => "llvm",
Matlab => "matlab",
Nginx => "nginx",
NodeREPL => "node-repl",
Ocaml => "ocaml",
PostgreSQL => "pgsql",
PowerShell => "powershell",
Prolog => "prolog",
Properties => "properties",
Scala => "scala",
Scheme => "scheme",
Scilab => "scilab",
Smalltalk => "smalltalk",
Tcl => "tcl",
Twig => "twig",
VBScript => "vbscript",
X86Asm => "x86asm",
]
});
impl ToString for HljsLang {
fn to_string(&self) -> String {
String::from(*HLJS_LANGS.get(self).unwrap())
}
}
impl FromStr for HljsLang {
type Err = fmt::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
HLJS_LANGS
.iter()
.find_map(|(&key, &value)| if value == s { Some(key) } else { None })
.ok_or_else(|| fmt::Error)
}
}
impl HljsLang {
pub(crate) fn to_url(language: impl Into<String>) -> String {
let language = language.into();
join_string!("/hljs/js/languages/", language, ".min.js")
}
}

View file

@ -0,0 +1,168 @@
//! <div align="center">
//!
//! <h1>PageTop HighlightJS</h1>
//!
//! <p>Integra <a href="https://highlightjs.org">highlight.js</a> para mostrar fragmentos de código con resaltado de sintaxis con <strong>PageTop</strong>.</p>
//!
//! [![Licencia](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?label=Licencia&style=for-the-badge)](#-license)
//! [![Doc API](https://img.shields.io/docsrs/pagetop-hljs?label=Doc%20API&style=for-the-badge&logo=Docs.rs)](https://docs.rs/pagetop-hljs)
//! [![Crates.io](https://img.shields.io/crates/v/pagetop-hljs.svg?style=for-the-badge&logo=ipfs)](https://crates.io/crates/pagetop-hljs)
//! [![Descargas](https://img.shields.io/crates/d/pagetop-hljs.svg?label=Descargas&style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-hljs)
//!
//! </div>
//!
//! ## Uso
//!
//! Añade `pagetop-hljs` a tu archivo `Cargo.toml`:
//!
//! ```rust#ignore
//! [dependencies]
//! pagetop-hljs = "<Version>"
//! ```
//!
//! Incluye `pagetop_hljs::HighlightJS` en las dependencias de la extensión o aplicación que lo
//! requiera:
//!
//! ```rust#ignore
//! use pagetop::prelude::*;
//!
//! impl ExtensionTrait for MyExtension {
//! // ...
//! fn dependencies(&self) -> Vec<ExtensionRef> {
//! vec![
//! // ...
//! &pagetop_hljs::HighlightJS,
//! // ...
//! ]
//! }
//!
//! fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
//! cfg.route("/snippet", service::web::get().to(hljs_sample));
//! }
//! // ...
//! }
//! ```
//!
//! Y finalmente añade tus fragmentos de código con resaltado de sintaxis en páginas web:
//!
//! ```rust#ignore
//! use pagetop_hljs::prelude::*;
//!
//! async fn hljs_sample(request: HttpRequest) -> ResultPage<Markup, ErrorPage> {
//! Page::new(request)
//! .with_component(HljsSnippet::with(
//! HljsLang::Rust,
//! r###"
//! // This is the main function.
//! fn main() {
//! // Print text to the console.
//! println!("Hello World!");
//! }
//! "###,
//! ))
//! .render()
//! }
//! ```
#![doc(
html_favicon_url = "https://raw.githubusercontent.com/manuelcillero/pagetop/main/static/favicon.ico"
)]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/manuelcillero/pagetop/main/static/pagetop_hljs.png"
)]
use pagetop::prelude::*;
// GLOBAL ******************************************************************************************
include_files!(hljs);
include_locales!(LOCALES_HLJS);
const HLJS_VERSION: &str = "11.7.0"; // Versión de la librería Highlight.js.
// API *********************************************************************************************
pub mod config;
pub mod context;
pub mod lang;
pub mod mode;
pub mod theme;
pub mod snippet;
pub mod prelude {
pub use crate::context::HljsContext;
pub use crate::lang::HljsLang;
pub use crate::mode::HljsMode;
pub use crate::theme::HljsTheme;
pub use crate::snippet::HljsSnippet;
}
/// Implementa [`ExtensionTrait`].
pub struct HighlightJS;
impl ExtensionTrait for HighlightJS {
fn description(&self) -> L10n {
L10n::t("hljs_description", &LOCALES_HLJS)
}
fn actions(&self) -> Vec<ActionBox> {
actions![action::page::AfterRenderBody::new(after_render_body)]
}
fn configure_service(&self, cfg: &mut service::web::ServiceConfig) {
include_files_service!(cfg, hljs => "/hljs");
}
}
// Define los recursos para la página según se use highlight.js en su versión "core" o "common".
fn after_render_body(page: &mut Page) {
use context::HljsContext;
use lang::HljsLang;
use mode::HljsMode;
use theme::HljsTheme;
let cx = page.context();
if cx.is_hljs_enabled() {
if let Some(languages) = cx.hljs_languages() {
match cx.hljs_mode() {
HljsMode::Core => {
cx.alter_assets(AssetsOp::AddJavaScript(
JavaScript::from("/hljs/js/core.min.js").with_version(HLJS_VERSION),
));
for l in languages {
cx.alter_assets(AssetsOp::AddJavaScript(
JavaScript::from(HljsLang::to_url(l)).with_version(HLJS_VERSION),
));
}
}
_ => {
cx.alter_assets(AssetsOp::AddJavaScript(
JavaScript::from("/hljs/js/highlight.min.js").with_version(HLJS_VERSION),
));
}
}
// Configura highlight.js (deshabilitando autodetección del lenguaje).
#[rustfmt::skip]
cx.alter_assets(AssetsOp::AddJavaScript(
JavaScript::inline("highlight.js", join_string!("
hljs.configure({
tabReplace: '", " ".repeat(config::SETTINGS.hljs.tabsize), "',
languages: [],
});
hljs.highlightAll();
")),
));
cx.alter_assets(AssetsOp::AddStyleSheet(
StyleSheet::from(HljsTheme::to_url(cx.hljs_theme().to_string()))
.with_version(HLJS_VERSION),
));
}
}
}

View file

@ -0,0 +1 @@
hljs_description = Display beautiful code snippets on web pages using the highlight.js library.

View file

@ -0,0 +1 @@
hljs_description = Incorpora fragmentos de código elegantes en páginas web usando la biblioteca highlight.js.

View file

@ -0,0 +1,41 @@
use serde::{Deserialize, Deserializer};
use std::fmt;
use std::str::FromStr;
#[derive(Clone, Copy, Debug)]
pub enum HljsMode {
Core,
Common,
}
impl ToString for HljsMode {
fn to_string(&self) -> String {
String::from(match self {
HljsMode::Core => "core",
HljsMode::Common => "common",
})
}
}
impl FromStr for HljsMode {
type Err = fmt::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"core" => Ok(HljsMode::Core),
"common" => Ok(HljsMode::Common),
_ => Err(fmt::Error),
}
}
}
impl<'de> Deserialize<'de> for HljsMode {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
HljsMode::from_str(&s).map_err(serde::de::Error::custom)
}
}

View file

@ -0,0 +1,65 @@
//! Add a new component to put code snippets on web pages.
use pagetop::prelude::*;
use crate::context::HljsContext;
use crate::lang::HljsLang;
#[derive(AutoDefault)]
/// Component to put code snippets on web pages.
pub struct HljsSnippet {
language: HljsLang,
snippet: String,
}
impl ComponentTrait for HljsSnippet {
fn new() -> Self {
HljsSnippet::default()
}
fn setup_before_prepare(&mut self, cx: &mut Context) {
cx.add_hljs_language(self.language());
}
fn prepare_component(&self, _cx: &mut Context) -> PrepareMarkup {
PrepareMarkup::With(html! {
pre {
code class=(join_string!("language-", self.language().to_string())) {
(self.snippet())
}
}
})
}
}
impl HljsSnippet {
pub fn with(language: HljsLang, code: impl Into<String>) -> Self {
HljsSnippet::new()
.with_language(language)
.with_snippet(code)
}
// Hljs BUILDER.
#[fn_builder]
pub fn with_language(mut self, language: HljsLang) -> Self {
self.language = language;
self
}
#[fn_builder]
pub fn with_snippet(mut self, snippet: impl Into<String>) -> Self {
self.snippet = snippet.into().trim().to_string();
self
}
// Hljs GETTERS.
pub fn language(&self) -> &HljsLang {
&self.language
}
pub fn snippet(&self) -> &String {
&self.snippet
}
}

View file

@ -0,0 +1,257 @@
use pagetop::prelude::*;
use serde::{Deserialize, Deserializer};
use std::collections::HashMap;
use std::str::FromStr;
use std::sync::LazyLock;
use std::fmt;
/// Supported themes.
///
/// Themes are defined as *PascalCase* enums in the code and correspond to *kebab-case* string
/// identifiers.
///
/// ```rust#ignore
/// use pagetop_hljs::HljsTheme;
///
/// assert_eq!(HljsTheme::AtelierPlateauLight.to_string(), "atelier-plateau-light".to_string());
/// ```
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum HljsTheme {
A11yDark,
A11yLight,
Agate,
AnOldHope,
Androidstudio,
ArduinoLight,
Arta,
Ascetic,
AtelierCave,
AtelierCaveLight,
AtelierDune,
AtelierDuneLight,
AtelierEstuary,
AtelierEstuaryLight,
AtelierForest,
AtelierForestLight,
AtelierHeath,
AtelierHeathLight,
AtelierLakeside,
AtelierLakesideLight,
AtelierPlateau,
AtelierPlateauLight,
AtelierSavanna,
AtelierSavannaLight,
AtelierSeaside,
AtelierSeasideLight,
AtelierSulphurpool,
AtelierSulphurpoolLight,
AtomOneDark,
AtomOneDarkReasonable,
AtomOneLight,
BrownPaper,
CodepenEmbed,
ColorBrewer,
Darcula,
Dark,
Default,
Devibeans,
Docco,
Dracula,
Far,
Foundation,
Framer,
Gigavolt,
Github,
Gml,
Googlecode,
GradientDark,
GradientLight,
Grayscale,
GruvboxDarkHard,
GruvboxLightHard,
Hopscotch,
Hybrid,
Idea,
IrBlack,
KimbieDark,
KimbieLight,
Lightfair,
Lioshi,
Magula,
MonoBlue,
MonokaiSublime,
NightOwl,
NnfxDark,
NnfxLight,
Obsidian,
Ocean,
Oceanicnext,
PandaSyntaxDark,
PandaSyntaxLight,
Pojoaque,
Purebasic,
QtcreatorDark,
QtcreatorLight,
Railcasts,
Rainbow,
Routeros,
SchoolBook,
ShapesOfPurple,
SolarizedDark,
SolarizedLight,
Srcery,
StackoverflowDark,
StackoverflowLight,
Sunburst,
TokioNightDark,
TokioNightLight,
Tomorrow,
TomorrowNight,
TomorrowNightBlue,
TomorrowNightBright,
Vs,
Vs2015,
Xcode,
Xt256,
Zenburn,
}
static HLJS_THEMES: LazyLock<HashMap<HljsTheme, &'static str>> = LazyLock::new(|| {
use HljsTheme::*;
hm![
A11yDark => "a11y-dark",
A11yLight => "a11y-light",
Agate => "agate",
AnOldHope => "an-old-hope",
Androidstudio => "androidstudio",
ArduinoLight => "arduino-light",
Arta => "arta",
Ascetic => "ascetic",
AtelierCave => "atelier-cave", // base16
AtelierCaveLight => "atelier-cave-light", // base16
AtelierDune => "atelier-dune", // base16
AtelierDuneLight => "atelier-dune-light", // base16
AtelierEstuary => "atelier-estuary", // base16
AtelierEstuaryLight => "atelier-estuary-light", // base16
AtelierForest => "atelier-forest", // base16
AtelierForestLight => "atelier-forest-light", // base16
AtelierHeath => "atelier-heath", // base16
AtelierHeathLight => "atelier-heath-light", // base16
AtelierLakeside => "atelier-lakeside", // base16
AtelierLakesideLight => "atelier-lakeside-light", // base16
AtelierPlateau => "atelier-plateau", // base16
AtelierPlateauLight => "atelier-plateau-light", // base16
AtelierSavanna => "atelier-savanna", // base16
AtelierSavannaLight => "atelier-savanna-light", // base16
AtelierSeaside => "atelier-seaside", // base16
AtelierSeasideLight => "atelier-seaside-light", // base16
AtelierSulphurpool => "atelier-sulphurpool", // base16
AtelierSulphurpoolLight => "atelier-sulphurpool-light", // base16
AtomOneDark => "atom-one-dark",
AtomOneDarkReasonable => "atom-one-dark-reasonable",
AtomOneLight => "atom-one-light",
BrownPaper => "brown-paper",
CodepenEmbed => "codepen-embed",
ColorBrewer => "color-brewer",
Darcula => "darcula", // base16
Dark => "dark",
Default => "default",
Devibeans => "devibeans",
Docco => "docco",
Dracula => "dracula", // base16
Far => "far",
Foundation => "foundation",
Framer => "framer", // base16
Gigavolt => "gigavolt", // base16
Github => "github",
Gml => "gml",
Googlecode => "googlecode",
GradientDark => "gradient-dark",
GradientLight => "gradient-light",
Grayscale => "grayscale",
GruvboxDarkHard => "gruvbox-dark-hard", // base16
GruvboxLightHard => "gruvbox-light-hard", // base16
Hopscotch => "hopscotch", // base16
Hybrid => "hybrid",
Idea => "idea",
IrBlack => "ir-black",
KimbieDark => "kimbie-dark",
KimbieLight => "kimbie-light",
Lightfair => "lightfair",
Lioshi => "lioshi",
Magula => "magula",
MonoBlue => "mono-blue",
MonokaiSublime => "monokai-sublime",
NightOwl => "night-owl",
NnfxDark => "nnfx-dark",
NnfxLight => "nnfx-light",
Obsidian => "obsidian",
Ocean => "ocean", // base16
Oceanicnext => "oceanicnext", // base16
PandaSyntaxDark => "panda-syntax-dark",
PandaSyntaxLight => "panda-syntax-light",
Pojoaque => "pojoaque",
Purebasic => "purebasic",
QtcreatorDark => "qtcreator-dark",
QtcreatorLight => "qtcreator-light",
Railcasts => "railcasts", // base16
Rainbow => "rainbow",
Routeros => "routeros",
SchoolBook => "school-book",
ShapesOfPurple => "shapes-of-purple",
SolarizedDark => "solarized-dark", // base16
SolarizedLight => "solarized-light", // base16
Srcery => "srcery",
StackoverflowDark => "stackoverflow-dark",
StackoverflowLight => "stackoverflow-light",
Sunburst => "sunburst",
TokioNightDark => "tokio-night-dark",
TokioNightLight => "tokio-night-light",
Tomorrow => "tomorrow", // base16
TomorrowNight => "tomorrow-night", // base16
TomorrowNightBlue => "tomorrow-night-blue",
TomorrowNightBright => "tomorrow-night-bright",
Vs => "vs",
Vs2015 => "vs2015",
Xcode => "xcode",
Xt256 => "xt256",
Zenburn => "zenburn", // base16
]
});
impl ToString for HljsTheme {
fn to_string(&self) -> String {
String::from(*HLJS_THEMES.get(self).unwrap())
}
}
impl FromStr for HljsTheme {
type Err = fmt::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
HLJS_THEMES
.iter()
.find_map(|(&key, &value)| if value == s { Some(key) } else { None })
.ok_or_else(|| fmt::Error)
}
}
impl<'de> Deserialize<'de> for HljsTheme {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
HljsTheme::from_str(&s).map_err(serde::de::Error::custom)
}
}
impl HljsTheme {
pub(crate) fn to_url(theme: impl Into<String>) -> String {
let theme = theme.into();
join_string!("/hljs/css/", theme, ".min.css")
}
}