✨ [hljs] Añade soporte a HighlightJS en PageTop
This commit is contained in:
parent
6701fb3e90
commit
7530cc69c2
210 changed files with 5277 additions and 2 deletions
58
packages/pagetop-hljs/src/config.rs
Normal file
58
packages/pagetop-hljs/src/config.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
//! Configuration settings for package.
|
||||
//!
|
||||
//! Example:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [hljs]
|
||||
//! mode = "core"
|
||||
//! theme = "zenburn"
|
||||
//! tabsize = 8
|
||||
//! ```
|
||||
//!
|
||||
//! Usage:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use pagetop_hljs::config;
|
||||
//!
|
||||
//! assert_eq!(config::SETTINGS.hljs.theme, "zenburn");
|
||||
//! ```
|
||||
//! See [`pagetop::config`] to learn how PageTop reads configuration files and uses settings.
|
||||
|
||||
use pagetop::prelude::*;
|
||||
|
||||
use crate::hljs_mode::HljsMode;
|
||||
use crate::hljs_theme::HljsTheme;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
include_config!(SETTINGS: Settings => [
|
||||
// [hljs]
|
||||
"hljs.mode" => "core",
|
||||
"hljs.theme" => "default",
|
||||
"hljs.tabsize" => 4,
|
||||
]);
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
/// Configuration settings for the [`[hljs]`](Hljs) section (see [`SETTINGS`] package).
|
||||
pub struct Settings {
|
||||
pub hljs: Hljs,
|
||||
}
|
||||
#[derive(Debug, Deserialize)]
|
||||
/// Section `[hljs]` of the configuration settings.
|
||||
///
|
||||
/// See [`Settings`].
|
||||
pub struct Hljs {
|
||||
/// Use ***core*** to import a minimal library and load only the languages added via
|
||||
/// [`add_hljs_language()`](crate::hljs_context::HljsContext::add_hljs_language). Alternatively,
|
||||
/// ***common*** imports an extended library containing around 40 popular languages (see
|
||||
/// [`HljsLang`](crate::hljs_lang::HljsLang)). Note that using the *common* library restricts
|
||||
/// you to the languages that are preloaded.
|
||||
/// Default value: *"core"*
|
||||
pub mode: HljsMode,
|
||||
/// Default theme in kebab-case used to display code snippets on web pages (see [`HljsTheme`]).
|
||||
/// Default value: *"default"*
|
||||
pub theme: HljsTheme,
|
||||
/// Number of spaces for *tab* character.
|
||||
/// Default value: *4*
|
||||
pub tabsize: usize,
|
||||
}
|
||||
95
packages/pagetop-hljs/src/hljs_context.rs
Normal file
95
packages/pagetop-hljs/src/hljs_context.rs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
use pagetop::prelude::*;
|
||||
|
||||
use crate::config;
|
||||
use crate::hljs_lang::HljsLang;
|
||||
use crate::hljs_mode::HljsMode;
|
||||
use crate::hljs_theme::HljsTheme;
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
// Context parameters.
|
||||
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";
|
||||
|
||||
/// Extend Context with HighlightJS features.
|
||||
pub trait HljsContext {
|
||||
/// Enable syntax highlighting in current context.
|
||||
fn enable_hljs(&mut self);
|
||||
|
||||
/// Preventing syntax highlighting in current context.
|
||||
fn disable_hljs(&mut self);
|
||||
|
||||
/// Force the use of the *highlight.js* ***core*** or ***common*** mode in current context,
|
||||
/// ignoring the [`config::SETTINGS.hljs.mode`](crate::config::Hljs#structfield.mode)
|
||||
/// configuration setting.
|
||||
fn force_hljs_mode(&mut self, mode: &HljsMode);
|
||||
|
||||
/// Add a new language to the context for processing code snippets. It is necessary to add at
|
||||
/// least one language to load the *highlight.js* library. Each
|
||||
/// [`Snippet`](crate::snippet::Snippet) component automatically adds its required language.
|
||||
fn add_hljs_language(&mut self, language: &HljsLang);
|
||||
|
||||
/// Change the theme in current context for displaying code snippets. The same theme is used for
|
||||
/// all snippets in the given context.
|
||||
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)
|
||||
}
|
||||
}
|
||||
246
packages/pagetop-hljs/src/hljs_lang.rs
Normal file
246
packages/pagetop-hljs/src/hljs_lang.rs
Normal 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
|
||||
/// 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::*;
|
||||
kv![
|
||||
// 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")
|
||||
}
|
||||
}
|
||||
41
packages/pagetop-hljs/src/hljs_mode.rs
Normal file
41
packages/pagetop-hljs/src/hljs_mode.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
257
packages/pagetop-hljs/src/hljs_theme.rs
Normal file
257
packages/pagetop-hljs/src/hljs_theme.rs
Normal 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
|
||||
/// 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::*;
|
||||
kv![
|
||||
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")
|
||||
}
|
||||
}
|
||||
166
packages/pagetop-hljs/src/lib.rs
Normal file
166
packages/pagetop-hljs/src/lib.rs
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
//! <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>
|
||||
//!
|
||||
//! [](#-license)
|
||||
//! [](https://docs.rs/pagetop-hljs)
|
||||
//! [](https://crates.io/crates/pagetop-hljs)
|
||||
//! [](https://crates.io/crates/pagetop-hljs)
|
||||
//!
|
||||
//! </div>
|
||||
//!
|
||||
//! ## Uso
|
||||
//!
|
||||
//! Añade `pagetop-hljs` a tu archivo `Cargo.toml`:
|
||||
//!
|
||||
//! ```rust
|
||||
//! [dependencies]
|
||||
//! pagetop-hljs = "<Version>"
|
||||
//! ```
|
||||
//!
|
||||
//! Incluye `pagetop_hljs::HighlightJS` en las dependencias del paquete o aplicación que lo requiera:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use pagetop::prelude::*;
|
||||
//!
|
||||
//! impl PackageTrait for MyPackage {
|
||||
//! // ...
|
||||
//! fn dependencies(&self) -> Vec<PackageRef> {
|
||||
//! 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
|
||||
//! use pagetop_hljs::prelude::*;
|
||||
//!
|
||||
//! async fn hljs_sample(request: HttpRequest) -> ResultPage<Markup, ErrorPage> {
|
||||
//! Page::new(request)
|
||||
//! .with_component(Snippet::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::*;
|
||||
|
||||
// API *********************************************************************************************
|
||||
|
||||
pub mod config;
|
||||
|
||||
pub mod hljs_context;
|
||||
pub mod hljs_lang;
|
||||
pub mod hljs_mode;
|
||||
pub mod hljs_theme;
|
||||
pub mod snippet;
|
||||
|
||||
// PRELUDE *****************************************************************************************
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::hljs_context::HljsContext;
|
||||
pub use crate::hljs_lang::HljsLang;
|
||||
pub use crate::hljs_mode::HljsMode;
|
||||
pub use crate::hljs_theme::HljsTheme;
|
||||
pub use crate::snippet::Snippet;
|
||||
}
|
||||
|
||||
include_files!(hljs);
|
||||
|
||||
include_locales!(LOCALES_HLJS);
|
||||
|
||||
/// Implementa [`PackageTrait`].
|
||||
pub struct HighlightJS;
|
||||
|
||||
impl PackageTrait 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");
|
||||
}
|
||||
}
|
||||
|
||||
// Versión de la librería Highlight.js.
|
||||
const HLJS_VERSION: &str = "11.7.0";
|
||||
|
||||
// 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 hljs_context::HljsContext;
|
||||
use hljs_lang::HljsLang;
|
||||
use hljs_mode::HljsMode;
|
||||
use hljs_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),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
1
packages/pagetop-hljs/src/locale/en-US/package.ftl
Normal file
1
packages/pagetop-hljs/src/locale/en-US/package.ftl
Normal file
|
|
@ -0,0 +1 @@
|
|||
hljs_description = Display beautiful code snippets on web pages using the highlight.js library.
|
||||
1
packages/pagetop-hljs/src/locale/es-ES/package.ftl
Normal file
1
packages/pagetop-hljs/src/locale/es-ES/package.ftl
Normal file
|
|
@ -0,0 +1 @@
|
|||
hljs_description = Incorpora fragmentos de código elegantes en páginas web usando la biblioteca highlight.js.
|
||||
63
packages/pagetop-hljs/src/snippet.rs
Normal file
63
packages/pagetop-hljs/src/snippet.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
//! Add a new component to put code snippets on web pages.
|
||||
|
||||
use pagetop::prelude::*;
|
||||
|
||||
use crate::hljs_context::HljsContext;
|
||||
use crate::hljs_lang::HljsLang;
|
||||
|
||||
#[derive(AutoDefault)]
|
||||
/// Component to put code snippets on web pages.
|
||||
pub struct Snippet {
|
||||
language: HljsLang,
|
||||
snippet: String,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Snippet {
|
||||
fn new() -> Self {
|
||||
Snippet::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 Snippet {
|
||||
pub fn with(language: HljsLang, code: impl Into<String>) -> Self {
|
||||
Snippet::new().with_language(language).with_snippet(code)
|
||||
}
|
||||
|
||||
// Hljs BUILDER.
|
||||
|
||||
#[fn_builder]
|
||||
pub fn alter_language(&mut self, language: HljsLang) -> &mut Self {
|
||||
self.language = language;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_builder]
|
||||
pub fn alter_snippet(&mut self, snippet: impl Into<String>) -> &mut 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
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue