Resaltado de sintaxis de código minimalista
En un artículo anterior [este: Cmder: La consola para Windows] te contábamos que nosotros estamos utilizamos el CMS Publii para generar el sitio en donde estas parado.
Publii es excelente. Punto. Tenemos pensando sacar una serie de artículos dedicados exclusivamente a Publii, cubriendo desde su funcionamiento básico hasta las creación de templates para el CMS.
Tabla de contenidos
Buscando la mejor manera de incluir código en nuestros artículos para que se vea "bonito", estuvimos evaluando varias alternativas, dado que Publii no integra (al menos a mayo de 2021) un syntax highlighter que permita, desde el editor, resaltar código fuente de diferentes lenguajes de programación.
Hay un issue en el repo del proyecto dedicado específicamente a este tema: Syntax highlighter?
Dentro de todas las alternativas que los usuarios ofrecen en el issue, encontramos una que se adapta a nuestro estilo pragmático y funcional (un eufemismo para perezoso), y es la solución propuesta por el usuario tcamde.
Básicamente tcamde propone lo siguiente:
"No quería añadir ese JS y CSS extra en cada página sólo para resaltar ocasionalmente el código. Así que uso esta solución:
- Copiar el código
- Pegar en alguna herramienta de resaltado de código en línea, por ejemplo, Syntax highlighter
- Obtenga el HTML de salida con estilos en línea
- Copie esto en su contenido como fragmento de HTML
Me funciona muy bien y es mucho más pequeño"
Lo que llamamos una solución minimalista. En vez de tener que lidiar con inclusiones de librerías JS, que se pueden romper cuando se cambia de versión de Publii y que genera más carga al sitio, simplemente generamos un HTML con estilo embebido a partir de la entrada, que puede ser un trozo de código de [casi] cualquiera de los lenguajes de programación más populares, que son, entre otros, los siguientes:
- arduino
- armasm (arm)
- xml (html, xhtml, rss, atom, xjb, xsd, xsl, plist)
- asciidoc (adoc)
- aspectj
- autohotkey
- autoit
- cmake (cmake.in)
- csp
- css
- d
- markdown (md, mkdown, mkd)
- dart
- ruby (rb, gemspec, podspec, thor, irb)
- erb
- erlang-repl
- erlang (erl)
- fix
- go (golang)
- golo
- gradle
- groovy
- haml
- handlebars (hbs, html.hbs, html.handlebars)
- haskell (hs)
- haxe (hx)
- hsp
- htmlbars
http (https) - inform7 (i7)
- ini (toml)
- irpf90
- java (jsp)
- javascript (js, jsx)
- json
- julia
- kotlin
- lasso (ls, lassoscript)
- mipsasm (mips)
- mizar
- perl (pl, pm)
- mojolicious
- monkey
- moonscript (moon)
- nginx (nginxconf)
- nimrod (nim)
- nix (nixos)
- nsis
- objectivec (mm, objc, obj-c)
- ocaml (ml)
- openscad (scad)
- oxygene
- parser3
- pf (pf.conf)
- php (php3, php4, php5, php6)
- powershell (ps)
- processing
- profile
- prolog
- protobuf
- puppet (pp)
- purebasic (pb, pbi)
- python (py, gyp)
- q (k, kdb)
- qml (qt)
- r
- rib
- roboconf (graph, instances)
- rsl
- ruleslanguage
- rust (rs)
- scala
- scheme
- scilab (sci)
- scss
- smali (smali)
- smalltalk (st)
- sml (ml)
- sqf (sqf)
¿Cómo se usa Online Syntax Higlighter?
El uso de Online Syntax Higlighter es muy sencillo. Para mostrar su funcionamiento vamos a utilizar código de la página Rosetta Code; seleccionar algunos de los lenguajes soportados y copiar y pegar en este artículo el resultado en HTML con los diferentes temas (estilos visuales) disponibles en la herramienta. Empecemos.
Primero mostraremos el procedimiento. Queremos convertir esta función JS en algo con más estilo, con colores y todo eso:
function factorial(n) {
//check our edge case
if (n < 0) { throw "Number must be non-negative"; }
var result = 1;
//we skip zero and one since both are 1 and are identity
while (n > 1) {
result *= n;
n--;
}
return result;
}
- Copiamos y pegamos el código en el textarea Unhighlighted Code.
- Seleccionamos el lenguaje.
- Seleccionamos el estilo.
- Presionamos el botón HIGHLIGHT!
- Copiamos el código HTML retornado.
El resultado es el siguiente:
Código: Javascript
Tema: Default
function factorial(n) {
//check our edge case
if (n < 0) { throw "Number must be non-negative"; }
var result = 1;
//we skip zero and one since both are 1 and are identity
while (n > 1) {
result *= n;
n--;
}
return result;
}
Tema: Androidstudio
function factorial(n) {
//check our edge case
if (n < 0) { throw "Number must be non-negative"; }
var result = 1;
//we skip zero and one since both are 1 and are identity
while (n > 1) {
result *= n;
n--;
}
return result;
}
Código: Groovy
Tema: Atelier Cave Dark
def rFact
rFact = { (it > 1) ? it * rFact(it - 1) : 1 as BigInteger }
Tema: Atelier Forest Light
def rFact
rFact = { (it > 1) ? it * rFact(it - 1) : 1 as BigInteger }
Código: Haskell
Tema: Codepen Embed
fac n
| n >= 0 = go 1 n
| otherwise = error "Negative factorial!"
where go acc 0 = acc
go acc n = go (acc * n) (n - 1)
Tema: Codepen Embed
fac n
| n >= 0 = go 1 n
| otherwise = error "Negative factorial!"
where go acc 0 = acc
go acc n = go (acc * n) (n - 1)
Código: Julia
Tema: Dark
function fact(n::Integer)
n < 0 && return zero(n)
f = one(n)
for i in 2:n
f *= i
end
return f
end
for i in 10:20
println("$i -> ", fact(i))
end
Tema: Dracula
function fact(n::Integer)
n < 0 && return zero(n)
f = one(n)
for i in 2:n
f *= i
end
return f
end
for i in 10:20
println("$i -> ", fact(i))
end
Código: Julia
Tema: Github
fun facti(n: Int) = when {
n < 0 -> throw IllegalArgumentException("negative numbers not allowed")
else -> {
var ans = 1L
for (i in 2..n) ans *= i
ans
}
}
fun factr(n: Int): Long = when {
n < 0 -> throw IllegalArgumentException("negative numbers not allowed")
n < 2 -> 1L
else -> n * factr(n - 1)
}
fun main(args: Array<String>) {
val n = 20
println("$n! = " + facti(n))
println("$n! = " + factr(n))
}
Tema: Gruvbox Dark
fun facti(n: Int) = when {
n < 0 -> throw IllegalArgumentException("negative numbers not allowed")
else -> {
var ans = 1L
for (i in 2..n) ans *= i
ans
}
}
fun factr(n: Int): Long = when {
n < 0 -> throw IllegalArgumentException("negative numbers not allowed")
n < 2 -> 1L
else -> n * factr(n - 1)
}
fun main(args: Array<String>) {
val n = 20
println("$n! = " + facti(n))
println("$n! = " + factr(n))
}
Código: Java
Tema: Gruvbox Light
import java.math.BigInteger;
import java.util.InputMismatchException;
import java.util.Scanner;
public class LargeFactorial {
public static long userInput;
public static void main(String[]args){
Scanner input = new Scanner(System.in);
System.out.println("Input factorial integer base: ");
try {
userInput = input.nextLong();
System.out.println(userInput + "! is\n" + factorial(userInput) + " using standard factorial method.");
System.out.println(userInput + "! is\n" + factorialRec(userInput) + " using recursion method.");
}catch(InputMismatchException x){
System.out.println("Please give integral numbers.");
}catch(StackOverflowError ex){
if(userInput > 0) {
System.out.println("Number too big.");
}else{
System.out.println("Please give non-negative(positive) numbers.");
}
}finally {
System.exit(0);
}
}
public static BigInteger factorialRec(long n){
BigInteger result = BigInteger.ONE;
return n == 0 ? result : result.multiply(BigInteger.valueOf(n)).multiply(factorial(n-1));
}
public static BigInteger factorial(long n){
BigInteger result = BigInteger.ONE;
for(int i = 1; i <= n; i++){
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
}
Tema: Monokai Sublime
import java.math.BigInteger;
import java.util.InputMismatchException;
import java.util.Scanner;
public class LargeFactorial {
public static long userInput;
public static void main(String[]args){
Scanner input = new Scanner(System.in);
System.out.println("Input factorial integer base: ");
try {
userInput = input.nextLong();
System.out.println(userInput + "! is\n" + factorial(userInput) + " using standard factorial method.");
System.out.println(userInput + "! is\n" + factorialRec(userInput) + " using recursion method.");
}catch(InputMismatchException x){
System.out.println("Please give integral numbers.");
}catch(StackOverflowError ex){
if(userInput > 0) {
System.out.println("Number too big.");
}else{
System.out.println("Please give non-negative(positive) numbers.");
}
}finally {
System.exit(0);
}
}
public static BigInteger factorialRec(long n){
BigInteger result = BigInteger.ONE;
return n == 0 ? result : result.multiply(BigInteger.valueOf(n)).multiply(factorial(n-1));
}
public static BigInteger factorial(long n){
BigInteger result = BigInteger.ONE;
for(int i = 1; i <= n; i++){
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
}
A modo resumen sobre resaltado de sintaxis de código minimalista
Las cosas solían ser tan sencillas. Con HTML y un poco de AJAX tenías suficiente para armarte un buen front end, pero parece que algunas cosas tienen que complicarse, y cada tanto un grupo de iluminados crea el nuevo super framework para hacer más complicado lo que se puede resolver con las herramientas que ya tenemos, pero bueno, esta discusión la dejamos para otro momento...
[La foto de portada es de Florian Olivo]
/ Súmate al boletín. No es gran cosa, pero es gratis 👇 /