• Publicidad

Procesando Markdown

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Procesando Markdown

Notapor r3daurii » 2015-12-14 09:33 @440

Hola chicos.

Mi enhorabuena por el foro y aquí va mi consulta.

Estoy escribiendo un parser en perl para markdown y posteriormente convertirlo a BBCode, sin embargo me quedo bastante bastante estancado.

Este es el código que he escrito hasta ahora, se encarga de transformar los bloques cabecera (H1, H2, H3, H4, H5, H6) en el equivalente de
Sintáxis: [ Descargar ] [ Ocultar ]
  1. [size=Ypt][/size] 
donde Ypt es un valor entre 60 y 10. Así, por ejemplo, un bloque del tipo H1 sería igual en bbcode a:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. [size=60pt][/size] 
.

En markdown, la sintaxis para un bloque H1-H6 es que obligatoriamente, la línea empiece por el símbolo de almohadilla (#), así que mi código lo busca y evalúa el tipo de bloque a crear, por ejemplo, si queremos un bloque H5, el código buscará 5 consecutivos (#####).

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. # Convert markdown headers style to bbcode
  2. #
  3. # r3daurii
  4.  
  5.  
  6. $file = $ARGV[0]; #Get the file from command line. other arguments will be ignored.
  7. chomp ($file);
  8.  
  9. open(FICH, "<$file") || die "No se puede abrir $file\n";
  10. while($linea = <FICH>){
  11.         $resul = mk_Headers($linea);
  12.         print $resul;
  13. }
  14.  
  15.  
  16. #Funcion - md_Headers()
  17. sub mk_Headers
  18. {
  19.         @h_Size = qw/JUNK [size=60pt] [size=50pt] [size=40pt] [size=30pt] [size=20pt] [size=10pt]/;
  20.         $linea = shift;
  21.         $ck_Header = index($linea,"#",0);
  22.  
  23.         if(($ck_Header==-1)||($ck_Header!=0)){
  24.                 return $linea;
  25.         }else{
  26.  
  27.  
  28.                 LOOP: for($count=0; $count<=6; $count++){
  29.                                 $h_Counter = index($linea,"#",$count);
  30.                                 if ($h_Counter == -1) {
  31.                                     $h_Counter = $count;
  32.                                         last LOOP;
  33.                                 }
  34.                 }
  35.         $linea =~ s/^\#{$h_Counter}/$h_Size[$h_Counter]/;
  36.         $linea =~ s/\Z/\[\/size\]/;
  37.         return $linea;
  38.         }
  39.        
  40. }
  41.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Podéis probar el script pasando un archivo de texto como único argumento, por ejemplo el siguiente:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. #H1 
  2. ##H2 
  3. ###H3 
  4. ####H4 
  5. #####H5 
  6. ######H6 
  7.  
  8. One more test # 
  9.  
  10. Si la línea no contiene al principio la almohadilla, no se lee # 


Y la salida de este al pasarlo por el programa será:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. [size=60pt]H1[/size] 
  2. [size=50pt]H2[/size] 
  3. [size=40pt]H3[/size] 
  4. [size=30pt]H4[/size] 
  5. [size=20pt]H5[/size] 
  6. [size=10pt]H6[/size] 
  7.  
  8. One more test # 
  9.  
  10. Si la línea no contiene al principio almohadilla, no se lee # 


Como veis, funcionar, funciona. Sin embargo, además de "feo" es, creo, muy ilegible :( el código en si.

El mayor problema lo tengo cuando hay etiquetas de apertura y cierre.

En markdown si queremos poner en negrita un texto, haríamos
Código: Seleccionar todo
**Este texto está en negrita**

y transformado a BBcode sería
Código: Seleccionar todo
[b]Este texto está en negrita[/b]

Hasta aquí, sencillo, pero ¿qué pasaría si tuviésemos algo como
Sintáxis: [ Descargar ] [ Ocultar ]
  1. *hola**** 
?, es decir, ¿cómo procesar y saber qué estilo tengo que aplicar al "hola".

Por otro lado, ¿cómo identificar cuál es el asterisco de apertura y de cierre en ese ejemplo?

No solo en ese ejemplo, debería funcionar en cualquier ejemplo.
r3daurii
Perlero nuevo
Perlero nuevo
 
Mensajes: 1
Registrado: 2015-12-12 14:35 @649

Publicidad

Re: Procesando Markown (orientación)

Notapor explorer » 2015-12-15 17:33 @773

Bienvenido a los foros de Perl en Español, r3daurii.

Si funciona, estupendo. Si quieres hacerlo más bonito... bueno, como estamos en el foro de Intermedio diremos que una buena solución sería la de crear una 'minigramática' usando expresiones regulares, que haga las transformaciones que queremos (al final te pongo un ejemplo).

Para detectar el caso de etiquetas de apertura y cierre se puede usar una expresión regular muy sencilla:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use feature 'say';
  3.  
  4. $x = 'Algo con ** Negrita ** y el resto';
  5.  
  6. $x =~ s{[*][*](.+?)[*][*]}{[b]${1}[/b]}g;
  7.  
  8. say $x;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Buscamos por los asteriscos, luego capturamos lo que sigue (.+), pero que esté justo antes (?) de otro par de paréntesis. Y si lo encontramos, lo sustituimos por las marcas clásicas.

Y para el tema de los asteriscos sobrantes... pues eso lo debería decir el estándar Markdown.

La solución que he encontrado es esta:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. #
  3. # Conversor de marcado Markdown a bbcode
  4. #
  5. use v5.18;
  6. use utf8::all;
  7. use autodie;
  8.  
  9. -e $ARGV[0] or die "Uso: $0 <archivo Markdown a procesar>\n";
  10.  
  11. # Mini gramática para Markdown
  12.  
  13. my @markdown = (
  14.     [
  15.         qr/^ (?<almohadillas> [#]+) (?<resto> .*?) \n $/msx,
  16.         q('[size=' . (70 - 10 * length $+{'almohadillas'}) . "pt]$+{'resto'}\[/size]\n")
  17.     ],
  18.     [
  19.         qr/[*][*]  (?<resto> .*? [ *]*) [*][*]/msx,
  20.         q('[b]' . $+{'resto'} . '[/b]')
  21.     ],
  22. );
  23.  
  24. sub mk_Headers {
  25.  
  26.     for my $regla_ref (@markdown) {
  27.  
  28.         $_[0] =~ s{$regla_ref->[0]}
  29.                   {$regla_ref->[1]}eemsxg;
  30.     }
  31. }
  32.  
  33.  
  34. #- Procesamiento
  35. open my $FILE, '<', $ARGV[0];
  36. while (<$FILE>) {
  37.     mk_Headers($_);
  38.     print;
  39. }
  40. close   $FILE;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

En la línea 13 definimos las reglas, consistentes en un patrón y en una expresión que se puede ejecutar.

Con este archivo de entrada
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
#H1
##H2
###H3
####H4
#####H5
######H6

One more test #

Si la línea no contiene al principio la almohadilla, no se lee #

Algo con ** texto en negrita** y algo más. Y más ** negrita **.

**hola****
 
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

sale este otro
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
[size=60pt]H1[/size]
[size=50pt]H2[/size]
[size=40pt]H3[/size]
[size=30pt]H4[/size]
[size=20pt]H5[/size]
[size=10pt]H6[/size]

One more test #

Si la línea no contiene al principio la almohadilla, no se lee #

Algo con [b] texto en negrita[/b] y algo más. Y más [b] negrita [/b].

[b]hola**[/b]
 
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


¡Ah!, y queda la solución obvia: usar Markdown::phpBB https://metacpan.org/pod/Markdown::phpBB ;)
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Intermedio

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 2 invitados