pagetop_hljs/
lib.rs

1//! <div align="center">
2//!
3//! <h1>PageTop HighlightJS</h1>
4//!
5//! <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>
6//!
7//! [![Licencia](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?label=Licencia&style=for-the-badge)](#-license)
8//! [![Doc API](https://img.shields.io/docsrs/pagetop-hljs?label=Doc%20API&style=for-the-badge&logo=Docs.rs)](https://docs.rs/pagetop-hljs)
9//! [![Crates.io](https://img.shields.io/crates/v/pagetop-hljs.svg?style=for-the-badge&logo=ipfs)](https://crates.io/crates/pagetop-hljs)
10//! [![Descargas](https://img.shields.io/crates/d/pagetop-hljs.svg?label=Descargas&style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-hljs)
11//!
12//! </div>
13//!
14//! ## Uso
15//!
16//! Añade `pagetop-hljs` a tu archivo `Cargo.toml`:
17//!
18//! ```rust#ignore
19//! [dependencies]
20//! pagetop-hljs = "<Version>"
21//! ```
22//!
23//! Incluye `pagetop_hljs::HighlightJS` en las dependencias de la extensión o aplicación que lo
24//! requiera:
25//!
26//! ```rust#ignore
27//! use pagetop::prelude::*;
28//!
29//! impl ExtensionTrait for MyExtension {
30//!     // ...
31//!     fn dependencies(&self) -> Vec<ExtensionRef> {
32//!         vec![
33//!             // ...
34//!             &pagetop_hljs::HighlightJS,
35//!             // ...
36//!         ]
37//!     }
38//!
39//!     fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
40//!         cfg.route("/snippet", service::web::get().to(hljs_sample));
41//!     }
42//!     // ...
43//! }
44//! ```
45//!
46//! Y finalmente añade tus fragmentos de código con resaltado de sintaxis en páginas web:
47//!
48//! ```rust#ignore
49//! use pagetop_hljs::prelude::*;
50//!
51//! async fn hljs_sample(request: HttpRequest) -> ResultPage<Markup, ErrorPage> {
52//!     Page::new(request)
53//!         .with_component(HljsSnippet::with(
54//!             HljsLang::Rust,
55//!             r###"
56//! // This is the main function.
57//! fn main() {
58//!     // Print text to the console.
59//!     println!("Hello World!");
60//! }
61//!             "###,
62//!         ))
63//!         .render()
64//! }
65//! ```
66
67#![doc(
68    html_favicon_url = "https://raw.githubusercontent.com/manuelcillero/pagetop/main/static/favicon.ico"
69)]
70#![doc(
71    html_logo_url = "https://raw.githubusercontent.com/manuelcillero/pagetop/main/static/pagetop_hljs.png"
72)]
73
74use pagetop::prelude::*;
75
76// GLOBAL ******************************************************************************************
77
78include_files!(hljs);
79
80include_locales!(LOCALES_HLJS);
81
82const HLJS_VERSION: &str = "11.7.0"; // Versión de la librería Highlight.js.
83
84// API *********************************************************************************************
85
86pub mod config;
87
88pub mod context;
89pub mod lang;
90pub mod mode;
91pub mod theme;
92
93pub mod snippet;
94
95pub mod prelude {
96    pub use crate::context::HljsContext;
97    pub use crate::lang::HljsLang;
98    pub use crate::mode::HljsMode;
99    pub use crate::theme::HljsTheme;
100
101    pub use crate::snippet::HljsSnippet;
102}
103
104/// Implementa [`ExtensionTrait`].
105pub struct HighlightJS;
106
107impl ExtensionTrait for HighlightJS {
108    fn description(&self) -> L10n {
109        L10n::t("hljs_description", &LOCALES_HLJS)
110    }
111
112    fn actions(&self) -> Vec<ActionBox> {
113        actions![action::page::AfterRenderBody::new(after_render_body)]
114    }
115
116    fn configure_service(&self, cfg: &mut service::web::ServiceConfig) {
117        include_files_service!(cfg, hljs => "/hljs");
118    }
119}
120
121// Define los recursos para la página según se use highlight.js en su versión "core" o "common".
122fn after_render_body(page: &mut Page) {
123    use context::HljsContext;
124    use lang::HljsLang;
125    use mode::HljsMode;
126    use theme::HljsTheme;
127
128    let cx = page.context();
129
130    if cx.is_hljs_enabled() {
131        if let Some(languages) = cx.hljs_languages() {
132            match cx.hljs_mode() {
133                HljsMode::Core => {
134                    cx.alter_assets(AssetsOp::AddJavaScript(
135                        JavaScript::from("/hljs/js/core.min.js").with_version(HLJS_VERSION),
136                    ));
137                    for l in languages {
138                        cx.alter_assets(AssetsOp::AddJavaScript(
139                            JavaScript::from(HljsLang::to_url(l)).with_version(HLJS_VERSION),
140                        ));
141                    }
142                }
143                _ => {
144                    cx.alter_assets(AssetsOp::AddJavaScript(
145                        JavaScript::from("/hljs/js/highlight.min.js").with_version(HLJS_VERSION),
146                    ));
147                }
148            }
149
150            // Configura highlight.js (deshabilitando autodetección del lenguaje).
151            #[rustfmt::skip]
152            cx.alter_assets(AssetsOp::AddJavaScript(
153                JavaScript::inline("highlight.js", join_string!("
154                    hljs.configure({
155                        tabReplace: '", " ".repeat(config::SETTINGS.hljs.tabsize), "',
156                        languages: [],
157                    });
158                    hljs.highlightAll();
159                ")),
160            ));
161
162            cx.alter_assets(AssetsOp::AddStyleSheet(
163                StyleSheet::from(HljsTheme::to_url(cx.hljs_theme().to_string()))
164                    .with_version(HLJS_VERSION),
165            ));
166        }
167    }
168}