diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..31af1d8 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,26 @@ +module.exports = { + env: { + browser: true, + es2021: true + }, + overrides: [ + ], + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: 'tsconfig.json' + }, + plugins: [ ], + rules: { + indent: ['error', 4, { SwitchCase: 1 }], + }, + settings: { + 'import/resolver': { + typescript: { + project: [ + 'tsconfig.json' + ] + } + } + } +} diff --git a/Build.PL b/Build.PL new file mode 100755 index 0000000..89e30b0 --- /dev/null +++ b/Build.PL @@ -0,0 +1,25 @@ +#!/usr/bin/env perl +use Module::Build; + +my $home = $ENV{HOME}; + +my $build = Module::Build->new( + module_name => 'BurguillosInfo', + license => 'AGPLv3', + dist_author => 'Sergio Iglesias ', + dist_abstract => 'The burguillos.info webpage.', + requires => { + 'Mojolicious' => 0, + 'Const::Fast' => 0, + 'Crypt::URandom' => 0, + 'Crypt::Bcrypt' => 0, + 'DBI' => 0, + 'DBD::Pg' => 0, + 'DateTime::Format::ISO8601.pm' => 0, + 'DateTime::Format::Mail.pm' => 0, + 'SVG' => 0, + 'XML::Twig' => 0, + 'JSON' => 0, + }, +); +$build->create_build_script; diff --git a/autobus-burguillos-tercer-mundo.webp b/autobus-burguillos-tercer-mundo.webp new file mode 100644 index 0000000..d6b9982 Binary files /dev/null and b/autobus-burguillos-tercer-mundo.webp differ diff --git a/babel.config.json b/babel.config.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/babel.config.json @@ -0,0 +1,2 @@ +{ +} diff --git a/burguillos_info.json.example b/burguillos_info.json.example index bf65a22..9dbc8ab 100644 --- a/burguillos_info.json.example +++ b/burguillos_info.json.example @@ -1,7 +1,9 @@ { "secrets": ["secret_change_for_pwgen_generated_one_with_at_least 255 chars"], - "bcrypt_pass_stats": ["change_for_bcrypted_password"], + "bcrypt_pass_stats": "change_for_bcrypted_password", "db": { "database": "example" - } + }, + "base_url": "https://burguillos.info", + "listen": "https:localhost:3555" } diff --git a/content/categories/animales.xml b/content/categories/animales.xml index 299adb3..9607a25 100644 --- a/content/categories/animales.xml +++ b/content/categories/animales.xml @@ -1,9 +1,9 @@ Animales y mascotas. -

Esta catogoría sirve como medio para hacerse eco de las noticias y plataformas relevantes para el bienestar de la fauna y mascotas de Burguillos.

+

Esta categoría sirve como medio para hacerse eco de las noticias y plataformas relevantes para el bienestar de la fauna y mascotas de Burguillos.

-

No se admitirán anuncios de compra-venta de animales tan solo adopciones solidarias y exclusivamente de animales domésticos esterilizados, en ningún caso se admitirá la transferencia de especies silvestres en este medio.

+

No se admitirán anuncios de compra-venta de animales, tan solo adopciones solidarias y exclusivamente de animales domésticos esterilizados, en ningún caso se admitirá la transferencia de especies silvestres en este medio.

Contacta con contact@owlcode.tech si necesitas realizar algún anuncio acorde a esta categoría.

diff --git a/content/categories/donde-comer.xml b/content/categories/donde-comer.xml new file mode 100644 index 0000000..8dc5814 --- /dev/null +++ b/content/categories/donde-comer.xml @@ -0,0 +1,54 @@ + + Donde comer en Burguillos. - Cartas y Menús. + +

Descubre los bares y restaurantes de Burguillos con sus cartas, menús y datos de contacto.

+

Aquí puedes encontrar información acerca de los negocios de hostelería de Burguillos.

+

Disfruta tu comida.

+

¿Quieres que tu comercio aparezca aquí? Contacta con contact@owlcode.tech

+
+ comercios + 0 + Donde comer + donde-comer + + + Pedir comida a domicilio en Burguillos. + reparto-a-domicilio-comida + 0 + Listado de sitios de comida con reparto a domicilio. + +

Cartas y Menús de Pizzerías, Hamburgueserías, Kebab, Restaurantes, Bares, etc.

+ +

Te filtramos todos los sitios según si puedes pedir a domicilio en Burguillos, todos los negocios listados incluyen carta, menú y teléfono de contacto. (O el medio de contacto pertinente para el negocio en caso de no ser el teléfono.)

+ +

¿Conoces algún negocio que debería estar listado aquí? Contacta con contact@owlcode.tech y lo añadiremos a este registro.

+
+
+ + Comer hamburguesas en Burguillos - Cartas y Menús. + hamburguesas + 0 + Listado de sitios de comida que preparan hamburguesas. + +

Hamburgueserias y todo tipo de establecimientos que preparan hamburguesas.

+ +

Te filtramos todos los sitios según si puedes pedirte la hamburguesa de la que tantas ganas tienes a continuación.

+ +

¿Conoces algún negocio que debería estar listado aquí? Contacta con contact@owlcode.tech y lo añadiremos a este registro.

+
+
+ + Pizzerías en Burguillos - Cartas y Menús. + pizzerias + 0 + Listado de sitios de comida que preparan pizzas. + +

Pizzerías y todo tipo de establecimientos que preparan pizzas.

+ +

Te filtramos todos los sitios según si puedes pedirte la pizza de la que tantas ganas tienes a continuación.

+ +

¿Conoces algún negocio que debería estar listado aquí? Contacta con contact@owlcode.tech y lo añadiremos a este registro.

+
+
+
+
diff --git a/content/categories/esta-pagina.xml b/content/categories/esta-pagina.xml index 9e8851f..5670362 100644 --- a/content/categories/esta-pagina.xml +++ b/content/categories/esta-pagina.xml @@ -2,9 +2,11 @@ Esta página.

¿Quieres promocionar tu negocio o asociación en Burguillos.info?

-

Contacta con Owlcode y te informaremos de los pasos a tomar.

+

Contacta con Owlcode y te informaremos de los pasos a tomar.

-

Esta página es software libre, puedes tomar cualquier parte del código de la página para tu propia web o programa mientras cumplas con la licencia AGPLv3 or later, puedes encontrar su código aquí.

+

Esta página es software libre, puedes tomar cualquier parte del código de la página para tu propia web o programa mientras cumplas con la licencia AGPLv3 or later, puedes encontrar su código aquí.

+ +

Si tienes conocimientos de HTML puedes crear tu propio artículo enviando una pull request a este enlace creando un fichero nuevo en content/posts, si no tienes conocimientos de HTML puedes contactar con nosotros y crearemos el artículo con el contenido que desees.

999 Esta página diff --git a/content/categories/index.xml b/content/categories/index.xml index c143d53..94bf3d9 100644 --- a/content/categories/index.xml +++ b/content/categories/index.xml @@ -1,11 +1,11 @@ - Portal de información de Burguillos. + Información de Burguillos. -

Burguillos.info no está afiliado con el Ayuntamiento de Burguillos.

+

Burguillos.info no está afiliado con el Ayuntamiento de Burguillos.

Esta página está destinada a informar de los sucesos y negocios de nuestro pueblo, cualquiera puede redactar una noticia para que aparezca en este medio mientras pase un proceso de revisión por parte del staff de Burguillos.info.

0 - Principio + Principio index
diff --git a/content/posts/0000002-horarios-autobuses-2022.xml b/content/posts/0000002-horarios-autobuses-2022.xml index eea0b8e..982414d 100644 --- a/content/posts/0000002-horarios-autobuses-2022.xml +++ b/content/posts/0000002-horarios-autobuses-2022.xml @@ -1,11 +1,14 @@ Burguillos.info 2022-11-09T22:38+00:00 - Horarios autobuses 2022. + Horarios autobuses Burguillos - Sevilla 2023. + 2023-05-03T03:40+00:00 Los horarios de autobuses de Burguillos. autobuses - horarios-autobuses-2022 + horarios-autobuses + +

Horarios Autobuses Castiblanco - Burguillos - Sevilla - Almaden de la Plata - Alcalá del Río - Rinconada - San Ignacio del Viar.

Destino Sevilla.

diff --git a/content/posts/0000003-migrantes-bienvenidos.xml b/content/posts/0000003-migrantes-bienvenidos.xml index d6158d2..8de26ac 100644 --- a/content/posts/0000003-migrantes-bienvenidos.xml +++ b/content/posts/0000003-migrantes-bienvenidos.xml @@ -5,13 +5,13 @@ Migrantes Bienvenidos.indexmigrantes-bienvenidos - +

Debido a la llegada continuada de personas que provienen de otros países, provincias y localidades, desde Burguillos.info hemos considerado oportuno dedicarle un post a todos aquel que no es natal de Burguillos pero que ya es un burguillero más.

La gente de Burguillos aprecia enormemente la riqueza cultural producto de la mezcla de culturas que se produce en el pueblo.

Queremos que todo aquel que no haya nacido en Burguillos pueda encontrar en este, nuestro pueblo un segundo hogar, por ello consideramos importante revindicar que las personas migrantes tengan acceso a todos sus derechos durante su estancia en Burguillos.

-

¿Vienes de fuera? En Burguillos.info nos gustaría hacernos eco de tu historia. Contacta con contact@owlcode.tech para contarnos tu experiencia.

+

¿Vienes de fuera? En Burguillos.info nos gustaría hacernos eco de tu historia. Contacta con contact@owlcode.tech para contarnos tu experiencia.

diff --git a/content/posts/0000004-suscribirse-rss.xml b/content/posts/0000004-suscribirse-rss.xml index b89cd69..3a698f7 100644 --- a/content/posts/0000004-suscribirse-rss.xml +++ b/content/posts/0000004-suscribirse-rss.xml @@ -14,41 +14,41 @@

En primer lugar vamos a instalar Feeder, un cliente de RSS de software libre para Android.

- Captura de pantalla de la aplicación Feeder en el Play Store. + Captura de pantalla de la aplicación Feeder en el Play Store.

Ahora visitarémos bajarémos abajo del todo de cualquier página de Burguillos.info y veremos un botón morado con un punto y dos curvas que nos indicará que nos suscribamos.

- Captura de pantalla del botón de suscribirse. + Captura de pantalla del botón de suscribirse.

Procederemos a dejar presionado sobre el botón hasta que nos aparezca este menú.

- Menú en el que seleccionar copiar enlace + Menú en el que seleccionar copiar enlace

Es muy importante que verifiquemos que la url termina en all.xml, si no nos habremos equivocado de botón, el otro idéntico es para suscribirse solo a una categoría, lo cual es útil si por ejemplo solo quieres enterarte de las noticias relacionadas con el autobús.

Una vez verificado, procederemos a pulsar sobre copiar enlace y abriremos Feeder, la aplicación que acabamos de descargar.

Una vez abierta pulsaremos en la esquina superior derecha sobre los tres puntos y veremos esta pantalla:

- Feeder con el menú abierto. + Feeder con el menú abierto.

Pulsaremos sobre "Add Feed" y nos saldrá esto:

- Feeder con un cuadro de dialogo para añadir feed abierto. + Feeder con un cuadro de dialogo para añadir feed abierto.

Dejamos presionado hasta que nos aparezca la opción de pegar el texto que copiamos antes y lo pegamos.

- Feeder con un cuadro de dialogo para añadir feed abierto con el siguiente contenido 'https://burguillos.info/all.rss'. + Feeder con un cuadro de dialogo para añadir feed abierto con el siguiente contenido 'https://burguillos.info/all.rss'.

Hecho esto pulsamos sobre buscar y si lo hemos hecho todo bien veremos lo siguiente:

- Feeder con un cuadro de dialogo para añadir feed abierto con el siguiente contenido 'https://burguillos.info/all.rss' y abajo un dialogo mostrando los datos de Feed de Burguillos.info. + Feeder con un cuadro de dialogo para añadir feed abierto con el siguiente contenido 'https://burguillos.info/all.rss' y abajo un dialogo mostrando los datos de Feed de Burguillos.info.

Pulsamos sobre el elemento que ha aparecido debajo del cuadro de busqueda y pasaremos a otra pantalla donde deberemos desplazarnos abajo del todo.

- Un dialogo donde se muestran preferencias para el Feed + Un dialogo donde se muestran preferencias para el Feed

Cuando pulsemos "Ok" habremos conseguido suscribirnos a Burguillos.info.

- Las noticias de Burguillos.info ahora aparecen listadas en la aplicación. + Las noticias de Burguillos.info ahora aparecen listadas en la aplicación.

RSS es más divertido cuando te suscribes a todos los sitios web que te interesen que provean RSS, de ese modo puedes ser el primero en enterarte de todo lo que esté pasando, y de forma totalmente anónima.

diff --git a/content/posts/0000005-kiosco-noemi.xml b/content/posts/0000005-kiosco-noemi.xml index cc7d5a7..4dac57d 100644 --- a/content/posts/0000005-kiosco-noemi.xml +++ b/content/posts/0000005-kiosco-noemi.xml @@ -1,64 +1,74 @@ Burguillos.info 2022-11-11T23:09+00:00 - La Tienda de Noemi. - La Tienda de Noemi. - comercios + Carta y Menú de la Tienda de Noemi en Burguillos. + 2023-05-03T20:10+00:00 + + Carta y Menú de la Tienda de Noemi en Burguillos. + donde-comer tienda-noemi + + hamburguesas + +

Hamburguesas, Pollofres, Gofres, Buñuelos, Montaditos, Salchipapas, entra y descubrelo.

+ Front door of the shop Tienda Noemi

Hoy os traemos un negocio de nueva apertura, "La Tienda de Noemi" localizado en Calle Albahaca Local 2 ACC, ideal para comer en Burguillos.

Este negocio abre de 17:00 a 22:00 de Lunes a Jueves y de 17:00 a 00:00 de Viernes a Domingo.

-

Además de vender multitud de bebidas, esta tienda ofrece bocadillos y otros productos preparados como buñuelos, además puedes dejar tu pedido encargado por teléfono en 698901484.

+

Además de vender multitud de bebidas, esta tienda ofrece bocadillos y otros productos preparados como buñuelos, además puedes dejar tu pedido encargado por teléfono en 698901484, deberás recogerlo en el establecimiento.

A continuación listamos el menú completo de comidas para haceros la boca agua.

Hamburguesas

    -
  1. Hamburguesa Simple. (Carne y queso.) 2€
  2. -
  3. Hamburguesa Completa. (Carne, cebolla, lechuga, tomate y queso.) 2.50€
  4. -
  5. Hamburguesa Super. (Carne, huevo, bacon, queso, cebolla y york.) 3.50€
  6. -
  7. Hamburguesa Yopi. (Filete pollo, queso, tomate, cebolla y lechuga.) 2.50€
  8. +
  9. Hamburguesa Simple. (Carne y queso.) 2€
  10. +
  11. Hamburguesa Completa. (Carne, cebolla, lechuga, tomate y queso.) 2.50€
  12. +
  13. Hamburguesa Super. (Carne, huevo, bacon, queso, cebolla y york.) 3.50€
  14. +
  15. Hamburguesa Yopi. (Filete pollo, queso, tomate, cebolla y lechuga.) 2.50€
  16. +

Bocadillos

- -
  • Bocadillo de pollo con queso. 2.50€
  • -
  • Bocadillo de pollo con cebolla, queso y tomate. 2.50€
  • -
  • Bocadillo de superpollo con queso, bacon, cochinito, tomate, cebolla y lechuga. 3€
  • -
  • Bocadillo de filete de lomo con queso. 2.50€
  • -
  • Bocadillo de filete de lomo con queso, tomate, cebolla y lechuga. 3€
  • -
  • Bocadillo de superlomo con queso, bacon, cochinito, tomate, cebolla y lechuga. 3€
  • -
  • Bocadillo de cochinito con queso. 2€
  • -
  • Bocadillo de cochinito con queso, bacon, cebolla, tomate y lechuga. 3€
  • -
  • Bocadillo de lomo adobado con queso. 2€
  • -
  • Bocadillo de lomo adobado con queso, bacon, cebolla, tomate y lechuga. 3€
  • -
  • Bocadillo de bacon y queso. 1.50€
  • -
  • Bocadillo vegetal con pollo. 3.50€
  • -
  • Serranito. (Pollo o lomo, tortilla francesa, pimiento, tomate y queso.) 4€
  • -
  • Super serranito. (Pollo o lomo, tortilla francesa, pimiento, cochinito, bacon, patatas, tomate y queso.) 6€
  • -
  • Perrito caliente simple. 2€
  • -
  • Sandwich de jamon york y queso. 1.50€
  • -
  • Sandwich vegetal. 2€
  • -
  • Montadito de pollo o lomo. 2€
  • +
      +
    1. Bocadillo de pollo con queso. 2.50€
    2. +
    3. Bocadillo de pollo con cebolla, queso y tomate. 2.50€
    4. +
    5. Bocadillo de superpollo con queso, bacon, cochinito, tomate, cebolla y lechuga. 3€
    6. +
    7. Bocadillo de filete de lomo con queso. 2.50€
    8. +
    9. Bocadillo de filete de lomo con queso, tomate, cebolla y lechuga. 3€
    10. +
    11. Bocadillo de superlomo con queso, bacon, cochinito, tomate, cebolla y lechuga. 3€
    12. +
    13. Bocadillo de cochinito con queso. 2€
    14. +
    15. Bocadillo de cochinito con queso, bacon, cebolla, tomate y lechuga. 3€
    16. +
    17. Bocadillo de lomo adobado con queso. 2€
    18. +
    19. Bocadillo de lomo adobado con queso, bacon, cebolla, tomate y lechuga. 3€
    20. +
    21. Bocadillo de bacon y queso. 1.50€
    22. +
    23. Bocadillo vegetal con pollo. 3.50€
    24. +
    25. Serranito. (Pollo o lomo, tortilla francesa, pimiento, tomate y queso.) 4€
    26. +
    27. Super serranito. (Pollo o lomo, tortilla francesa, pimiento, cochinito, bacon, patatas, tomate y queso.) 6€
    28. +
    29. Perrito caliente simple. 2€
    30. +
    31. Sandwich de jamon york y queso. 1.50€
    32. +
    33. Sandwich vegetal. 2€
    34. +
    35. Montadito de pollo o lomo. 2€
    36. +

    Otros

    -
  • Nuggets con patatas. (8 unidades.) 3.50€
  • -
  • Croquetas con patatas. (8 unidades.) 3.50€
  • -
  • Salchipapa pequeña. 2€
  • -
  • Salchipapa grande. 3.50€
  • -
  • Patatas pequeñas. 2€
  • -
  • Patatas grandes. 3.50€
  • -
  • Crepes. 3.50€
  • -
  • Tortitas. 3.50€
  • -
  • Gofres con chocolate. 3.50€
  • -
  • Buñuelos. 3.50€
  • -
  • Pollofres. 4€
  • +
      +
    1. Nuggets con patatas. (8 unidades.) 3.50€
    2. +
    3. Croquetas con patatas. (8 unidades.) 3.50€
    4. +
    5. Salchipapa pequeña. 2€
    6. +
    7. Salchipapa grande. 3.50€
    8. +
    9. Patatas pequeñas. 2€
    10. +
    11. Patatas grandes. 3.50€
    12. +
    13. Crepes. 3.50€
    14. +
    15. Tortitas. 3.50€
    16. +
    17. Gofres con chocolate. 3.50€
    18. +
    19. Buñuelos. 3.50€
    20. +
    21. Pollofres. 4€
    -

    ¿Quieres ver tu negocio localizado en Burguillos en este espacio? Contacta con contact@owlcode.tech.

    +

    ¿Quieres ver tu negocio localizado en Burguillos en este espacio? Contacta con contact@owlcode.tech.

    diff --git a/content/posts/0000006-evento-mairami.xml b/content/posts/0000006-evento-mairami.xml index 6d3ee8c..fb45d72 100644 --- a/content/posts/0000006-evento-mairami.xml +++ b/content/posts/0000006-evento-mairami.xml @@ -4,7 +4,7 @@ Cartel de Cuentacuentos Infantil "Don Juan Tenorio".Cartel de Cuentacuentos Infantil "Don Juan Tenorio".index - + cuentacuentos-infantil-don-juan-tenorio

    Hoy os traemos información de una representación teatral que se ha producido este mismo día en Alcalá del Rio.

    @@ -12,7 +12,7 @@

    La obra ha sido representada por la Asociación de Teatro Mairami cuyos origenes están fuertemente ligados a Burguillos y los habitantes de Burguillos profesamos infinito cariño por los que conforman esta asociación por su inestimable contribución a la propagación de la cultura.

    Adjuntamos algunas imágenes relevantes, el cartel de la obra y una fotografía de otra representación que muestra a una parte de los actores de Mairami.

    - Cartel de la obra. - Elenco de actores. + Cartel de la obra. + Elenco de actores.
    diff --git a/content/posts/0000007-mas-informacion-cuentacuentos.xml b/content/posts/0000007-mas-informacion-cuentacuentos.xml index 32cfec0..a04a792 100644 --- a/content/posts/0000007-mas-informacion-cuentacuentos.xml +++ b/content/posts/0000007-mas-informacion-cuentacuentos.xml @@ -4,7 +4,7 @@ Información fresca del Cuentacuentos de Mairami del 2022/11/12.Información fresca del Cuentacuentos de Mairami del 2022/11/12.index - + cuentacuentos-infantil-don-juan-tenorio-imagenes

    En la tarde de ayer 12 de noviembre, la Compañía de teatro MAIRAMI, realizó un Cuentacuentos basado en la obra de José Zorrilla "Don Juan Tenorio", una versión que combina verso y prosa, con semejanzas actuales para que el público infantil pueda entender los entresijos de esta obra maestra.

    @@ -13,11 +13,11 @@

    Ademas traemos las cuentas de Instagram y Facebook de Mairami para que podais seguir todas sus novedades @teatro_mairami y A.C. Mairami

    Sin más demora ahí van las imagenes y el vídeo completo.

    - La compañia mairami interpreta un cuentacuentos de Don Juan Tenorio - La compañia mairami interpreta un cuentacuentos de Don Juan Tenorio - La compañia mairami interpreta un cuentacuentos de Don Juan Tenorio - La compañia mairami interpreta un cuentacuentos de Don Juan Tenorio - La compañia mairami interpreta un cuentacuentos de Don Juan Tenorio + La compañia mairami interpreta un cuentacuentos de Don Juan Tenorio + La compañia mairami interpreta un cuentacuentos de Don Juan Tenorio + La compañia mairami interpreta un cuentacuentos de Don Juan Tenorio + La compañia mairami interpreta un cuentacuentos de Don Juan Tenorio + La compañia mairami interpreta un cuentacuentos de Don Juan Tenorio
    diff --git a/content/posts/0000008-taller-de-macrame.xml b/content/posts/0000008-taller-de-macrame.xml index 929f634..5a3b416 100644 --- a/content/posts/0000008-taller-de-macrame.xml +++ b/content/posts/0000008-taller-de-macrame.xml @@ -4,10 +4,10 @@ Últimas plazas para Taller de Macrame.Últimas plazas para Taller de Macrame.talleres - + ultimas-plazas-taller-de-macrame - Poster del taller + Poster del taller

    Ultima hora, nos hemos enterado de un taller de Macramé planeado para el 26 de Noviembre de 10:00 a 18:00 en la Mercería la Gallina Costurera localizada en Avenida Pepe Luna.

    El taller está organizado por Maka Guijo y costará 45€ por persona.

    diff --git a/content/posts/0000009-venta-de-calendarios-nala.xml b/content/posts/0000009-venta-de-calendarios-nala.xml index 36aad60..7f780f6 100644 --- a/content/posts/0000009-venta-de-calendarios-nala.xml +++ b/content/posts/0000009-venta-de-calendarios-nala.xml @@ -4,10 +4,10 @@ Venta de calendarios de la Plataforma N.A.L.A. Venta de calendarios de la Plataforma N.A.L.A. animales-y-mascotas - + venta-de-calendarios-plataforma-nala - Logo plataforma NALA + Logo plataforma NALA

    Plataforma N.A.L.A. es una entidad que se dedica a buscar un hogar a mascotas abandonadas en las cercanias de Burguillos.

    Debido al deplorable estado en el que suelen encontrarse a los animales y a la necesidad de esterilizarlos antes de darlos en adopción para evitar la proliferación de más animales abandonados, N.A.LA acumula durante el año deudas veterinarias que sufraga con la emisión de un calendario solidario.

    diff --git a/content/posts/0000010-clases-de-guitarra-eduardo.xml b/content/posts/0000010-clases-de-guitarra-eduardo.xml index 7f6e0db..f2406a4 100644 --- a/content/posts/0000010-clases-de-guitarra-eduardo.xml +++ b/content/posts/0000010-clases-de-guitarra-eduardo.xml @@ -4,10 +4,10 @@ Clases de Guitarra con Eduardo Trassierra. Clases de Guitarra con Eduardo Trassierra. talleres - + clases-guitarra-eduardo-trassierra - Imagen de las clases de guitarra, el profesor Eduardo Trassierra + Imagen de las clases de guitarra, el profesor Eduardo Trassierra

    Os informamos de que se ha abierto el plazo de inscripción para clases de guitarra impartidas por Eduardo Trassierra, un reputado guitarrista a escala nacional.

    Las clases estarán localizadas en nuestro municipio, Burguillos.

    diff --git a/content/posts/0000011-fin-de-semana-de-cultura.xml b/content/posts/0000011-fin-de-semana-de-cultura.xml index 8977784..44fae9e 100644 --- a/content/posts/0000011-fin-de-semana-de-cultura.xml +++ b/content/posts/0000011-fin-de-semana-de-cultura.xml @@ -4,10 +4,10 @@ Fin de semana de cultura. Fin de semana de cultura. index - + fin-de-semana-de-cultura - Cartel de las obras. + Cartel de las obras.

    Hoy nos hacemos eco de una noticia que hemos encontrado en la página web del ayuntamiento, el XII Certamen de Teatro de Burguillos.

    Vamos a proceder a fusilar el artículo para que lo podáis leer aquí y dejaremos el enlace para que podaís visitar el original:

    No hagas planes para este fin de semana y vive con nosotros el #Certamen de #Teatro "Villa de #Burguillos" Os mostramos las obras seleccionadas y los horarios de representación:

    diff --git a/content/posts/0000012-bar-el-bocaton.xml b/content/posts/0000012-bar-el-bocaton.xml index 12c4538..7c9d0f9 100644 --- a/content/posts/0000012-bar-el-bocaton.xml +++ b/content/posts/0000012-bar-el-bocaton.xml @@ -1,13 +1,20 @@ Burguillos.info 2022-11-18T00:00+00:00 - El Bocatón - Café - Bar - Pastelería - Pizzeria - Hamburguesería. - El Bocatón - Café - Bar - Pastelería - Pizzeria - Hamburguesería. - comercios - + 2023-05-02T00:00+00:00 + El Bocatón - Burguillos - Carta y Menú + El Bocatón - Burguillos - Carta y Menú + donde-comer + el-bocaton + + reparto-a-domicilio-comida + hamburguesas + pizzerias + - Exterior del Bar Bocatón. +

    Café - Bar - Pastelería - Pizzeria - Hamburguesería

    + Exterior del Bar Bocatón.

    Damos la bienvenida a un nuevo negocio al directorio de Burguillos.info, El Bocatón.

    El Bocatón es un Café - Bar ubicado al lado del Parque del Barrio Lejos, (Calle Naranjo, 11) ideal para tomarte algo mientras tus hijos juegan en el parque.

    @@ -45,7 +52,7 @@

    Chapata Pizza

    Adjuntamos imagen de la Chapata Pizza para que podáis verla antes de mostar las opciones.

    - Chapata Pizza + Chapata Pizza
    1. Completa con dos ingredientes. 4€
    2. @@ -130,9 +137,5 @@

      Aprovechamos este espacio final tras terminar de listar el menú para adjuntaros más imágenes del local y desearos una feliz comida.

      - Exterior del Bar Bocatón. - Exterior del Bar Bocatón. - Exterior del Bar Bocatón. - diff --git a/content/posts/0000013-obra-el-silencio.xml b/content/posts/0000013-obra-el-silencio.xml index d9e5530..9d8575d 100644 --- a/content/posts/0000013-obra-el-silencio.xml +++ b/content/posts/0000013-obra-el-silencio.xml @@ -5,9 +5,9 @@ ¡Silencio, se piensa!. index silencio-se-piensa - + - Portada silencio, se piensa + Portada silencio, se piensa

      Hemos recibido información adicional de la obra de teatro del día 2022/11/19, desde Burguillos.info procedemos a comunicaros las novedades:

      🎭 Continuamos con el Certamen de teatro “Villa de Burguillos “ con la 2da compañía finalista , Producciones el dramaturgo de Jerez de la Frontera ( Cádiz) y que estrenan en primicia su obra : ¡Silencio, se piensa ! Escrita por José Mateos , director de la compañía. Los jóvenes actores Luis Guerrero y Emilio Rosales son los en cargados de envolvernos en esta magnífica historia que narra el futuro incierto de dos actores que acaban de quedarse sin trabajo... obra que recurre al auto sacramental como género clásico poco usado hoy día por los dramaturgos contemporáneos . Estilo que ejercen de forma magistral induciendo sutilmente al bonito ejercicio de pensar con profundidad y espíritu autocrítico. ¿¿Te vas a perder esta oportunidad?? Te esperamos a las 20 :00 H en el teatro municipal. 🎭

      diff --git a/content/posts/0000014-policlinica-burguillos.xml b/content/posts/0000014-policlinica-burguillos.xml index 2fc226f..f692f83 100644 --- a/content/posts/0000014-policlinica-burguillos.xml +++ b/content/posts/0000014-policlinica-burguillos.xml @@ -1,13 +1,15 @@ Burguillos.info 2022-11-19T18:03+00:00 - Centro Médico Juan Manuel Pérez Sanchez - Centro Médico Juan Manuel Pérez Sanchez + Centro Médico Juan Manuel Pérez Sanchez - Datos de Contacto - Pedir Cita + Centro Médico Juan Manuel Pérez Sanchez - Datos de Contacto - Pedir Cita + 2023-05-03T00:59+00:00 comercios centro-medico-juan-manuel-perez-sanchez - + - Cartel de Centro Médico Juan Manuel Pérez Sanchez +

      Clinica Dental, Ortodoncia, Pedagogía y Podolologia en Burguillos.

      + Cartel de Centro Médico Juan Manuel Pérez Sanchez

      La clínica Juan Manuel Pérez Sanchez es un centro de atención a la salud dedicado a las siguientes especialidades:

        @@ -23,6 +25,6 @@

        Localizado en Calle la Fuente número 24.

        - Entrada de la clínica + Entrada de la clínica diff --git a/content/posts/0000015-meson-bar-cristobal.xml b/content/posts/0000015-meson-bar-cristobal.xml index 2c1d79f..3c4d91c 100644 --- a/content/posts/0000015-meson-bar-cristobal.xml +++ b/content/posts/0000015-meson-bar-cristobal.xml @@ -1,21 +1,26 @@ Burguillos.info 2022-11-22T09:47+00:00 - Mesón - Bar - Cristobal - Mesón - Bar - Cristobal - comercios + Mesón - Bar - Cristobal - Carta y Menú. + Mesón - Bar - Cristobal - Carta y Menú. + 2023-05-03T02:34+02:00 + donde-comer bar-cristobal - + + hamburguesas + + - Entrada al Mesón - Bar Cristobal. -

        El Mesón - Bar Cristobal ubicado en la Calle los Palmeros número 30 es una opción ideal para tomarte un café o comer en Burguillos.

        +

        Menú actualizado con nuevos precios y productos 2023-05-03

        + Entrada al Mesón - Bar Cristobal. +

        El Mesón - Bar Cristobal ubicado en la Calle los Palmeros número 32 es una opción ideal para tomarte un café o comer en Burguillos.

        Además acepta pedidos a domicilio durante los meses Noviembre, Diciembre, Enero y Febrero de Martes a Domingo durante las noches.

        El número de teléfono de contacto es 621210460.

        A continuación procedemos a dejar la carta para que podáis realizar el pedido que deseeis:

        -

        Entrantes

        +

        Entrantes

    @@ -55,18 +60,18 @@ + + - - + + - -
    Ensalada Mixta-- 4€--
    Ensalada Normal-- 3€--
    -

    Aperitivos

    +

    Aperitivos

    @@ -117,7 +122,166 @@
    8€
    -

    Pescados

    +

    En Temporada

    + + + + + + + + + + + + + + + + + + + +
    Tapa1/2 RaciónRación
    Cabrillas2.50€5€10€
    Caracoles2.50€5€10€
    +

    Ibéricos

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Tapa1/2 RaciónRación
    Secreto--S-P--
    Lagrimitas3.50€7€14€
    Lagarto3.50€7€14€
    Tocinito3€6€12€
    +

    Carnes

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Tapa1/2 RaciónRación
    Carne Asá3€6€12€
    Solomillo al Whisky3.50€8€16€
    Solomillo a la Pimienta3.50€8€16€
    Solomillo al Roquefort3.50€8€16€
    Churrasco de Pollo/Cerdo--5.50€--
    Mini Serranito de Pollo/Cerdo--3€--
    Serranito de Pollo/Cerdo--5€--
    Montadito de Pollo/Cerdo--2.50€--
    Montadito de Gambas--3€--
    Mantecadito de Pollo/Cerdo--3€--
    Pechuga de Pollo--5.50€--
    Pinchito de Pollo/Cerdo--3€--
    Brocheta de Solomillo--7€--
    Hamburguesa Simple--2.50€--
    Hamburguesa Completa--3€--
    Hamburguesa de Buey--5€--
    +

    Pescados

    @@ -180,6 +344,12 @@ + + + + + + @@ -199,160 +369,7 @@
    8€ 14€
    Pescado Variado.-7€-
    Pez Espada ----
    -

    En temporada

    - - - - - - - - - - - - - - - - - - - -
    Tapa1/2 RaciónRación
    Cabrillas2.50€5€10€
    Caracoles2.50€5€10€
    -

    Carnes

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Tapa1/2 RaciónRación
    Carne Asá3€6€12€
    Churrasco de Pollo/Cerdo--5.50€--
    Mini Serranito de Pollo/Cerdo--3€--
    Serranito de Pollo/Cerdo--5€--
    Montadito de Pollo/Cerdo--2.50€--
    Montadito de Gambas--3€--
    Pechuga de Pollo--5.50€--
    Pinchito de Pollo/Cerdo--3€--
    Solomillo al Whisky3.50€8€16€
    Solomillo a la Pimienta3.50€8€16€
    Solomillo al Roquefort3.50€8€16€
    Brocheta de Solomillo--7€--
    Hamburguesa Simple--2.50€--
    Hamburguesa Completa--3€--
    Hamburguesa de Buey--5€--
    -

    Ibéricos

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Tapa1/2 RaciónRación
    Secreto--S-P--
    Lagrimitas3.50€7€14€
    Lagarto3.50€7€14€
    Tocinito3.50€7€14€
    -

    Cazuelitas

    +

    Cazuelitas

    @@ -366,6 +383,18 @@ + + + + + + + + + + + + @@ -378,24 +407,14 @@ - - - - - - - - - - - -
    6€ 12€
    Bacalao con Tomate3€6€12€
    Espinacas3€6€12€
    Carne con tomate 3€6€ 12€
    Espinacas3€6€12€
    Bacalao con Tomate3€6€12€
    -

    Postres

    + +

    Postres

    1. Arroz con leche 2.50€
    2. Natillas 2.50€
    3. -
    4. Helados Precio Variable
    5. +
    6. Flan de Huevo 2.50€
    7. +
    8. Helados Nestle Precio Variable

    Por último desde Burguillos.info os indicamos que el precio por el servicio de pan y picos por comensal es de 0.30€ y que tenéis la posibilidad de pedir un extra en salsas por 0.50€.

    diff --git a/content/posts/0000016-social-burguillos-info.xml b/content/posts/0000016-social-burguillos-info.xml index 9e8c6eb..4fe8a0c 100644 --- a/content/posts/0000016-social-burguillos-info.xml +++ b/content/posts/0000016-social-burguillos-info.xml @@ -4,9 +4,10 @@ Diaspora para las masas. Diaspora para las masas. index - + social-burguillos-info +

    Este servicio ha sido temporalmente descontinuado por falta de actualizaciones por parte de sus desarrolladores. Disculpen las molestias

    Hoy desde Burguillos.info os traemos por un lado un nuevo método de estar al tanto de las novedades de la web y por otro una forma nueva de comunicarte con los otros burguilleros y burguilleras.

    La nueva web social.burguillos.info es eso y más, dicha web es una instancia de Diaspora, una red social de software libre que te permite interactuar con quien quieras de la red independientemente de en que instancia te encuentras mediante un algoritmo conocido como federación.

    @@ -17,24 +18,24 @@

    En primer lugar en la parte de abajo de la web podrás encontrar un nuevo icono a parte del ya conocido de suscripción por RSS, uno que es una suerte de asteristo con un circulo negro alrededor. - Indicaciones para encontrar el icono de suscripción por Diaspora + Indicaciones para encontrar el icono de suscripción por Diaspora

    Al pulsar sobre el llegarás a nuestro perfil en dicha red.

    - Perfil de Burguillos.info en Diaspora. + Perfil de Burguillos.info en Diaspora.

    No obstante aun no podremos seguir a la cuenta porque aun no nos hemos registrado. Como he dicho, podemos seguir a Burguillos.info desde cualquier instancia, puedes elegir una de diaspora.fediverse.observer o usar la propia de Burguillos.info, en este caso voy a seguir el tutorial desde la instancia de Burguillos.info.

    - Perfil de Burguillos.info en Diaspora con la opción de registrarse marcada. + Perfil de Burguillos.info en Diaspora con la opción de registrarse marcada.

    Pulsamos sobre "Create account" para registrarnos y empezar a disfrutar Diaspora.

    - Datos de inscripción rellenos. + Datos de inscripción rellenos.

    Rellenamos la información con nuestro correo electrónico, nombre de usuario, contraseña repetida dos veces y resolvemos la comprobación de que somos humanos, para despues presionar de nuevo en "Create Account".

    Si tienes dificultades en este paso o cualquier otro contacta con contact@owlcode.tech.

    - Menú pidiendonos más datos que queramos incluir. + Menú pidiendonos más datos que queramos incluir.

    Una vez hayamos completado la inscripción con exito aparecerá una nueva pantalla ofreciendonos a introducir más información para hacer la experiencia mejor como un avatar y hashtags para que otros usuarios sepan cuales son tus intereses.

    @@ -42,29 +43,29 @@

    Una vez hayas terminado de personalizar a tu gusto tu cuenta, pulsamos sobre "Awesome! Take me to diaspora* >>"

    - Vista principal de Diaspora*. + Vista principal de Diaspora*.

    Al llegar a esta imagen habremos terminado el proceso de registro en Diaspora*, ahora querremos seguir a Burguillos.info, para ello pulsamos en el icono de suscripción en la parte de abajo de este artículo.

    - Indicaciones para encontrar el icono de suscripción por Diaspora + Indicaciones para encontrar el icono de suscripción por Diaspora

    Seguimos el enlace.

    - El perfil de Burguillos.info con el nombre de usuario al estilo email seleccionado. + El perfil de Burguillos.info con el nombre de usuario al estilo email seleccionado.

    Seleccionamos el nombre de usuario, que será siempre parecido a una dirección de correo electrónico.

    - El nombre de usuario copiado en la barra de busqueda. + El nombre de usuario copiado en la barra de busqueda.

    Copiamos dicho nombre en la barra de busqueda y pulsamos intro.

    - La nueva pantalla tras pulsar sobre add contact y indicando que se pulse sobre Acquaintances. + La nueva pantalla tras pulsar sobre add contact y indicando que se pulse sobre Acquaintances.

    Pulsamos sobre "Add contact" y aparecerá un menú desplegable donde pulsaremos sobre Acquaintances para indicar que eres conocido de Burguillos.info, con usuarios con los que tengas mayor confianza puedes pulsar Family, Friend o Work, de ese modo puedes redactar tus posts para que lleguen solo a las personas que deseés.

    Cuando lo hagas y pulses a "stream", verás que en tu timeline ya aparecen los posts de Burguillos.info.

    - Timeline lleno de posts de Burguillos.info + Timeline lleno de posts de Burguillos.info

    Tan solo me queda desearte una feliz estancia en Diaspora*.

    diff --git a/content/posts/0000017-servidor-de-chat-burguillos.xml b/content/posts/0000017-servidor-de-chat-burguillos.xml index f3471c9..abf7d8c 100644 --- a/content/posts/0000017-servidor-de-chat-burguillos.xml +++ b/content/posts/0000017-servidor-de-chat-burguillos.xml @@ -4,7 +4,7 @@ Servidor de chat de Burguillos. Servidor de chat de Burguillos. index - + chat-burguillos

    Desde Burguillos.info creemos en las tecnologías de comunicación descentralizadas, debido a ello configuramos hace poco un servidor de Diaspora* para que los burguilleros y burguilleras puedan usarlo como foro sustituyendo a Facebook.

    @@ -26,22 +26,22 @@

    En primer lugar tendrás que descargar un cliente de XMPP, os recomiendo usar Conversations ya que implementa encriptación de extremo a extremo, lo que significa que el dueño de tu servidor nunca podrá leer tus mensajes. (Si usas bien esa feature verificando las claves para evitar que sean interceptadas.)

    Una vez lo hayas instalado, cuando abras la nueva aplicación encontrarás una pantalla como esta.

    - Pantalla de bienvenida de Conversations + Pantalla de bienvenida de Conversations

    Como aun no tenemos una cuenta pulsaremos sobre "Create new account".

    - Pantalla de selección entre servidor por defecto o custom. + Pantalla de selección entre servidor por defecto o custom.

    Una vez hayamos pulsado nos hará una nueva pregunta, si queremos usar el proveedor de Conversations.im o otro.

    Para favorecer la descentralización y aprovechar el servidor del pueblo pulsaremos sobre "Use my own provider", si quisieses escoger la primera opción también podrías hablar con la gente suscrita a Burguillos.info, la única desventaja es que no podrías ver las salas públicas creadas en Burguillos.info, tendrías que buscarlas manualmente por su nombre.

    - Pantalla de introducción de datos + Pantalla de introducción de datos

    Ahora la aplicación nos pide que introduzcamos el nuevo usuario a crear, para crear tu nombre de usuario deberás hacerlo como si fuese un email terminado en @burguillos.info, por ejemplo manuelsanchez@burguillos.info, anarodriguez@burguillos.info, asociacionX@burguillos.info...

    Debes tener cuídado al introducir la contraseña, ya que si la pierdes no tendrás ninguna forma de recuperarla y perderás el acceso a la cuenta, de todos modos crear una nueva es gratis y puedes tener tantas como quieras.

    - Pantalla de selección de avatar + Pantalla de selección de avatar

    Ahora nos da la opción de introducir un avatar para hacer nuestra cuenta única y que la gente pueda reconocernos en la red, un avatar es una pequeña imagen que puede ser una foto tuya, de tu mascota, de algo que te guste...

    diff --git a/content/posts/0000018-25-n-di-no-a-la-violencia-machista.xml b/content/posts/0000018-25-n-di-no-a-la-violencia-machista.xml index 04786a2..32498f6 100644 --- a/content/posts/0000018-25-n-di-no-a-la-violencia-machista.xml +++ b/content/posts/0000018-25-n-di-no-a-la-violencia-machista.xml @@ -5,9 +5,9 @@ Di no a la violencia machísta. index 25-n-di-no-a-la-violencia-machista - + - Simbolo feminista + Simbolo feminista

    Hoy, día 25 de Noviembre se celebra el día contra la violencia machísta.

    Se estima que el setenta por ciento de las mujeres sufre este tipo de violencia a lo largo de su vida1

    diff --git a/content/posts/0000019-problemas-tecnicos.xml b/content/posts/0000019-problemas-tecnicos.xml new file mode 100644 index 0000000..fa567c4 --- /dev/null +++ b/content/posts/0000019-problemas-tecnicos.xml @@ -0,0 +1,48 @@ + + Sergio Iglesias (Lead Developer) + 2023-04-30T23:58:37+02:00 + Problemas técnicos. + Explicación sobre porque no se ha podido acceder a la web estos últimos días. + index + + problemas-tecnicos + +

    Burguillos.info ha vuelto a la normalidad tras 5 días inoperativo, te explicamos las razones.

    + + A fiber cable cutted down + +

    En burguillos.info siempre hemos pensado que tenía lógica tener el servidor localizado en Burguillos y no + en otro país como Alemania. Debido a que ningún proveedor de VPS tiene localización en nuestro municipio decidimos + alojar la web en un pequeño ordenador en mi casa que es también sede de la empresa que lleva burguillos.info, + owlcode.tech.

    + +

    Esta decisión técnica tuvo sentido a pesar de existir proveedores que la podrían alojar con menos problemas habituales + en Burguillos como pueden ser los frecuentes cortes en el suministro eléctrico. Pensamos que si vas a hacer una web sobre Burguillos que menos que + el servidor se encuentre aquí fomentando la economía local y no la economía de otra localidad o país.

    + +

    No obstante en un despreciable acto de mala voluntad alguien decidió que el cable de fibra óptica de esta web + le estorbaba y lo cortó. Hasta aquí todo tiene fácil solución y no hubiese justificado más de + dos días de tiempo inactivo ya que el técnico de la fibra llegó al día siguiente y realizó el diagnóstico + de que la falta de conectividad se debía a que el cable de fibra óptica había sido seccionado de forma completa + resultando de ese modo imposible que la información fluyese por el mismo, por lo que al día siguiente procedería + a la reinstalación completa del cable.

    + +

    No obstante uno de los vecinos.- Que en ningún modo está demostrado que tuviese nada que ver con el corte del canal + de comunicación a pesar de haber estado realizando una obra donde reorganizó la disposición del cableado en su fachada.- + Se negó en rotundo a la reposición del cable, fundamental no solo para el funcionamiento de esta web sino también para + mi trabajo.

    + +

    A día de hoy la sede de esta empresa continúa sin un canal de fibra óptica para operar debido a las reiteradas + negativas del sujeto en cuestión.

    + +

    El servidor ha sido desplazado a otra localización donde permanecerá hasta que se restaure el servicio y desde + owlcode.tech nos reservamos el derecho a ejercer acciones legales.

    + +

    Tras el desplazamiento al inspeccionar el servicio social.burguillos.info hemos constatado que no es compatible + con versiones soportadas por la comunidad del lenguaje de programación Ruby, por lo que hemos decidido apagarlo + y sustituirlo por otro servicio de naturaleza federada como puede ser Mastodon. Aceptamos sugerencias sobre qué + software de red social os gustaría ver en este sitio.

    + +

    Esperamos desde burguillos.info que paséis una mejor semana que la que yo he tenido.

    +
    +
    diff --git a/content/posts/0000020-subida-de-precio-autobuses.xml b/content/posts/0000020-subida-de-precio-autobuses.xml new file mode 100644 index 0000000..81ef149 --- /dev/null +++ b/content/posts/0000020-subida-de-precio-autobuses.xml @@ -0,0 +1,34 @@ + + Burguillos.info + 2023-04-30T23:58:37+02:00 + Subida de precio de los autobuses. + Precios premium por un servicio tercermundista, el estado actual de los autobuses de Burguillos. + index + + subida-precio-autobus-burguillos + + Image of an overloaded bus in a third world country. + +

    Precios premium por un servicio tercermundista, el estado actual de los autobuses de Burguillos.

    + +

    Damas ha incrementado una vez más el precio del autobús de 2.31€ a 2.50€, + mientras el descuento del gobierno nos llega mal y tarde.

    + +

    Este es solo uno más de la lista de atropellos que la empresa Damas lleva + realizados en la línea de nuestra localidad con los infinitos retrasos de las líneas, + la gente que esta línea.- Supuestamente deficitaria.- Ha dejado en tierra por estar el + autobús demasiado lleno y horarios que no permiten el desarrollo sostenible efectivo + de nuestra localidad.

    + +

    Desde Damas nos avocan a utilizar coche para desplazarnos a los municipios cercanos, un + medio de transporte extremadamente contaminante comparativamente al autobús haciendo de + este modo lobby de la industria automovilística que está destruyendo nuestro planeta.

    + +

    Los burguilleros y burguilleras debemos plantarnos ante este insulto a la inteligencia + que es querernos vender como un descuento una subida de precio, debemos hacer saber a + Damas que con Burguillos no se juega.

    + +

    Por Burguillos y nuestro planeta pasemos a la acción, si no nos quieren escuchar obliguemosles + a hacerlo.

    +
    +
    diff --git a/content/posts/0000021-pizzeria-los-naranjos.xml b/content/posts/0000021-pizzeria-los-naranjos.xml new file mode 100644 index 0000000..b38cc35 --- /dev/null +++ b/content/posts/0000021-pizzeria-los-naranjos.xml @@ -0,0 +1,495 @@ + + Burguillos.info + 2023-05-01T15:35+00:00 + 2023-05-03T15:35+00:00 + Carta y Menú de Los Naranjos en Burguillos. + Carta y Menú de Los Naranjos en Burguillos. + + donde-comer + pizzeria-los-naranjos + + reparto-a-domicilio-comida + hamburguesas + pizzerias + + +

    Pizzería, Hamburguesería, Kebab, Pescado, Aliños.

    + The front door of the pizzeria +

    Hoy añadimos a este directorio un clásico en las cenas de los fines + de semana de los habitantes de Burguillos, la Pizzería los Naranjos.

    + +

    Las especialidades de este negocio son las hamburguesas, pizzas y kebabs, + imprescindible si buscas un sitio para comer en Burguillos.

    + +

    El negocio se encuentra en Avenida Arroyo Paso de la Villa numero 22, el teléfono es el siguiente 657 375 878, envían pedidos a domicilio dentro de esta localidad.

    + +

    Adjuntamos el menú de los Naranjos a continuación en formato de texto legible con discapacidad visual: (En ningún caso los ingredientes deben usarse como lista de alérgenos, pregunte en el establecimiento o por teléfono al hacer su pedido.)

    + +

    Pizzas

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NúmeroNombreIngredientesPrecio
    1MargaritaTomate, mozzarella y orégano.4.50€
    2AtúnTomate, mozzarella, atún y orégano.5.00€
    3BaconTomate, mozzarella, bacon y orégano.5.00€
    4JamónTomate, mozzarella, jamón y orégano.5.00€
    5ChorizoTomate, mozzarella, chorizo y orégano.5.00€
    6AnchoasTomate, mozzarella, anchoas, pimiento y orégano.5.50€
    7SerranaTomate, mozzarella, chorizo, jamón y orégano.5.50€
    8NapolitanaTomate, mozzarella, atún, champiñones, jamón y orégano.6.00€
    9ItalianaTomate, mozzarella, jamón york, atún y orégano.6.00€
    104 EstacionesTomate, mozzarella, alcachofas, jamón york, anchoas, salami y orégano.6.00€
    11Barbacoa de polloTomate, mozzarella, pollo, salsa barbacoa y orégano.6.00€
    12Barbacoa de cerdoTomate, mozzarella, cerdo, salsa barbacoa y orégano.6.00€
    13RomanaTomate, mozzarella, champiñones, atún y orégano.6.00€
    14CarbonaraMozzarella, salsa carbonara, bacon, champiñones, cebolla y orégano.6.50€
    15VegetalTomate, mozzarella, atún, huevo, alcachofa, espárragos y orégano.6.50€
    16MediterraneaTomate, mozzarella, pollo, bacon, queso gouda, pimiento, cebolla y orégano.6.50€
    17HawaianaTomate, mozzarella, bacon, queso gouda, piña y orégano.6.50€
    18PepperoniTomate, mozzarella, pepperoni y orégano.6.50€
    194 QuesosTomate, mozzarella, 4 quesos y orégano.6.50€
    20PimientosTomate, mozzarella, champiñones, pimientos fritos, cebolla y orégano.6.50€
    21Rulo de queso de cabraTomate, mozzarella, queso de rulo de cabra y cebolla caramelizada.7.00€
    22Especial de la casaTomate, mozzarella, aceitunas verdes, palitos de pollo crujiente y orégano.5.00€
    235 quesos.Tomate, mozzarella, 4 quesos, roquefort y orégano.7.00€
    +

    *Puedes solicitar un ingrediente extra en tu pizza por 0.50€.

    + +

    Hamburguesas.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio
    Mixta 100g2.00€
    Mixta 150g3.50€
    Ternera 150g4.00€
    Buey 250g5.00€
    Super XXL7.50€
    Crispy Chicken3.50€
    + +

    Kebab.

    + +

    Recordad especificar si quereis durum o pita para evitar sorpresas. Haz + tu kebab menú por un euro más y recibe patatas y refresco.

    + + + + + + + + + + + + + + + + + + + + + + +
    Nombre.Precio.
    Kebab pollo completo.4.50€
    Kebab pollo solo carne.5.50€
    Kebab ternera completo.4.50€
    Kebab ternera solo carne.5.50€
    + +

    Perritos.

    + + + + + + + + + + + + + + + + + + + + + + +
    Nombre.Ingredientes.Precio.
    SimpleN/A2.00€
    VegetalLechuga, tomate, cebolla y pepinillos.2.80€
    Completo de la casaLechuga, cebolla crujiente, queso fundido y 4 salsas.3.50€
    + +

    Baguettes.

    + +

    Recuerda pedir la salsa para acompañar si quieres alguna.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Nombre.Precio.
    Tortilla de patatas.2.80€
    Cochinito.2.80€
    Bacon y queso.2.80€
    Jamón york y queso.2.50€
    Pechuga de pollo, lechuga y tomate.3.50€
    Atún y bacon.3.60€
    Pollo empanado.3.50€
    + +

    Especiales de la casa.

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Nombre.Precio.
    Costilla BBQ.6.80€
    Palitos de pollo crujiente.2.50€
    Alitas adobadas.2.50€
    Nuggets POP.2.50€
    Cazuela de papas gratinadas.4.00€
    + +

    Aliños.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Nombre.Precio tapa.Precio plato.
    Ensaladilla.3.00€5.50€
    Papas aliñadas.2.50€5.00€
    Plato tomate.N/A3.50€
    Pimientos asados.3.00€5.50€
    Aliño de huevas.3.00€6.00€
    Boquerones en vinagre.3.50€6.50€
    Anchoas del cantabrico.1.20€/udN/A
    + +

    Pescado.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Nombre.Precio.
    Boquerones.4.50€
    Lomo de merluza.5.50€
    Chipirón a la plancha.6.80€
    Puntillitas.5.60€
    Choco.6.60€
    Cazón en adobo.5.50€
    Calamares.6.00€
    Gambas.S/M
    Pez espada.8.50€
    + +

    Carne.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Nombre.Precio.
    Lomo al whisky.6.50€
    Churrasco de cerdo.6.00€
    Churrasco de pollo.5.50€
    Carrillada ibérica.6.90€
    Flamenquín cordobés.4.50€
    Pollo empanado.5.00€
    +

    *Carnes a la brasa durante los fines de semana.

    + +

    Salsas.

    + +

    ¡Acuerdate de pedirlas si las quieres!

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Nombre.
    Ali Oli.
    Barbacoa.
    Mayonesa.
    Ketchup.
    Mostaza.
    Salsa brava.
    Moho picón.
    Salsa whisky.
    + +

    Además de todo esto hacen Paella y Arroz con bogavante por encargo.

    + +

    ¿Quieres ver tu negocio localizado en Burguillos en este espacio? Contacta con contact@owlcode.tech.

    + +
    +
    diff --git a/content/posts/0000022-el-fogon-de-segovia.xml b/content/posts/0000022-el-fogon-de-segovia.xml new file mode 100644 index 0000000..05e650d --- /dev/null +++ b/content/posts/0000022-el-fogon-de-segovia.xml @@ -0,0 +1,258 @@ + + Burguillos.info + 2023-05-04T15:08+00:00 + Carta y Menú de El Fogón de Segovia en Burguillos. + Carta y Menú de El Fogón de Segovia en Burguillos. + + donde-comer + el-fogon-de-segovia + + Front door of 'El Fogón de Segovia' + +

    Especialidad en cordero y cochinillo asado al horno de leña, información para reservar.

    + +

    Este restaurante de estilo segoviano prepara unos platos que son una delicia. ¡Si no lo has probado todavía no sabes lo que te pierdes!

    + + +

    El Fogón de Segovia está localizado en Avenida Alcalde José Cuesta Godoy número 35, su horario es de Martes a Domingo de 10:00-17:00.

    + +

    Las reservas se deberán hacer exclusivamente por este teléfono 670 950 789, su página web oficial es https://elfogondesegovia.com.

    + +

    Adjuntamos la carta a continuación.

    + +

    ¡Disfruta de tu almuerzo!

    + +

    Entrantes.

    + +

    Entrantes.

    + +
      +
    • Morcilla Segovia.
    • +
    • Chorizo de la olla.
    • +
    • Calamares en su tinta.
    • +
    • Mollejas de cordero.
    • +
    • Riñones de cordero. (Preguntar)
    • +
    • Patatas fritas redondas.
    • +
    • Foie.
    • +
    • Foie fresco.
    • +
    • Setas al ajillo.
    • +
    • Croquetas caseras.
    • +
    • Chocos fritos.
    • +
    • Gambas cocidas.
    • +
    • Tostas con salmorejo y jamón.
    • +
    • Tostas con salmorejo y anchoas.
    • +
    • Queso viejo.
    • +
    • Caña de lomo.
    • +
    • Jamón ibérico.
    • +
    • Judiones de la granja.
    • +
    • Ensaladilla rusa.
    • +
    • Revuelto de setas.
    • +
    • Revuelto de ajetes.
    • +
    • Revuelto de habas.
    • +
    • Alcachofas con jamón.
    • +
    • Pisto de la casa.
    • +
    • Pimientos rellenos. (Huevo y atún)
    • +
    • Sopa castellana.
    • +
    • Sopa de picadillo.
    • +
    • Cebolla Frita.
    • +
    + +

    Ensaladas.

    + +
      +
    • Ensalada del fogón. (Pimientos rojos asados)
    • +
    • Ensalada mixta.
    • +
    • Ensalada de aguacates y maíz.
    • +
    • Ensalada de cogollos.
    • +
    • Ensalada de cogollos y anchoas.
    • +
    • Ensalada verde.
    • +
    • Ensalada de remolacha. (Lechuga, maíz, nueces, miel)
    • +
    + +

    Aperitivos.

    + +
      +
    • Pan.
    • +
    • Aceitunas.
    • +
    + +

    Medias y Tapas.

    + +

    Medias raciones.

    + +
      +
    • Tostas con salmorejo y jamón.
    • +
    • Tostas con salmorejo y anchoas.
    • +
    • Ensaladilla rusa.
    • +
    • Jamón ibérico.
    • +
    • Caña de lomo ibérico.
    • +
    • Queso viejo.
    • +
    • Chorizo de la olla.
    • +
    • Morcilla de Segovia.
    • +
    • Croquetas caseras.
    • +
    • Pisto de la casa.
    • +
    • Lomo de la olla.
    • +
    • Foie de ave.
    • +
    • Aliño atún.
    • +
    + +

    Tapas. (Solo en barra)

    + +
      +
    • Tostas con salmorejo y anchoas.
    • +
    • Tostas con salmorejo y jamón.
    • +
    • Ensaladilla.
    • +
    • Jamón ibérico.
    • +
    • Caña de lomo ibérico.
    • +
    • Queso viejo.
    • +
    • Chorizo de la olla.
    • +
    • Croquetas caseras.
    • +
    • Chocos fritos.
    • +
    • Pisto de la casa.
    • +
    • Lomo de cerdo de la olla.
    • +
    • Morcilla de Segovia.
    • +
    • Variado de chacinas. (Plato pequeño)
    • +
    + +

    Segundos platos.

    + +

    Asados. (Por encargo)

    + +
      +
    • Cuarto de cochinillo. (Para dos personas)
    • +
    • Cuarto de cordero. (Para dos personas)
    • +
    + +

    Carnes.

    + +
      +
    • Solomillo de ternera.
    • +
    • Entrecot de angus.
    • +
    • Entrecot de buey.
    • +
    • Entrecot de ternera.
    • +
    • Chuletillas de cordero.
    • +
    • Presa ibérica.
    • +
    • Lomo de la olla.
    • +
    • Solomillo de cerdo. (En salsa)
    • +
    • Solomillo de cerdo ibérico. (A la plancha)
    • +
    • Magret de pato.
    • +
    • Filete de pollo.
    • +
    • Carne de cerdo. (En salsa)
    • +
    + +

    Pescados.

    + +
      +
    • Salmón a la plancha.
    • +
    • Pez espada.
    • +
    • Lenguado a la plancha.
    • +
    • Bacalao rebozado o con tomate.
    • +
    + +

    Carta de vinos.

    + +

    Vinos de la casa.

    + +
      +
    • Rioja "22 pies" crianza.
    • +
    • Ribera del Duero "Valdrinal Entrega"
    • +
    + +

    Riojas.

    + +
      +
    • Izadi "Crianza"
    • +
    • Cuatro rayas 40 Vendimias "Crianza"
    • +
    + +

    Riberas del duero.

    + +
      +
    • Vega Sicilia Valbuena 5°
    • +
    • Malleolus "Crianza"
    • +
    • Jaros "Crianza"
    • +
    • Tomás Postigo "Crianza"
    • +
    • Pesquera "Crianza"
    • +
    • Matarromera "Crianza"
    • +
    • Viña Pedrosa "Crianza"
    • +
    • Mauro "Crianza"
    • +
    • Emilio Moro "Finca Resalso"
    • +
    • Pruno "Cosecha"
    • +
    • Yllera "Crianza"
    • +
    + +

    Toro.

    + +
      +
    • Flor de Vetus "Crianza"
    • +
    + +

    Blancos.

    + +
      +
    • Yllera Cinco.5 Verdejo Afrutado.
    • +
    • Palestra Rueda. (Semi seco afrutado)
    • +
    + +

    Rosados.

    + +
      +
    • Peñascal "Aguja"
    • +
    + +

    Cavas.

    + +
      +
    • Brut Reserva Perelada.
    • +
    + +

    Champagne.

    + +
      +
    • Laurent Perrier
    • +
    + +

    Postres.

    + +

    Postres caseros.

    + +
      +
    • Helado de nata con chocolate.
    • +
    • Helado de turrón.
    • +
    • Crema catalana.
    • +
    • Flan de huevo.
    • +
    • Tocinillo con almendras.
    • +
    • Tarta de la casa.
    • +
    • Tarta de chocolate.
    • +
    • Tarta de queso.
    • +
    • Peras al vino tinto.
    • +
    • Tarta "Pachanga" (Galleta, flan y chocolate)
    • +
    • Sorbete de limón.
    • +
    • Torrijas de vino. (Solo en temporada)
    • +
    • Canutillos con crema pastelera.
    • +
    • Tarta de cuajada.
    • +
    • Tiramisú.
    • +
    • Ponche segoviano.
    • +
    • Mousse de limón.
    • +
    • Mousse de chocolate.
    • +
    • Arroz con leche.
    • +
    • Poléa. (Temporada de invierno)
    • +
    • Pestiños. (Temporada de invierno)
    • +
    + +

    Helados (Nestle)

    + +
      +
    • Tarta helada al whisky.
    • +
    • Bombones de vainilla.
    • +
    • Copa de fresa y nata.
    • +
    • Bombón de almendras.
    • +
    • Mikolápiz.
    • +
    • Fantasmikos.
    • +
    • Bombón de nata.
    • +
    + +

    ¿Quieres ver tu negocio localizado en Burguillos en este espacio? Contacta con contact@owlcode.tech.

    + +
    +
    diff --git a/content/posts/0000023-pizzeria-genuino.xml b/content/posts/0000023-pizzeria-genuino.xml new file mode 100644 index 0000000..7bb3296 --- /dev/null +++ b/content/posts/0000023-pizzeria-genuino.xml @@ -0,0 +1,460 @@ + + Burguillos.info + 2023-05-04T22:32+00:00 + Carta y Menú de la Pizzería Genuino en Burguillos. + Carta y Menú de la Pizzería Genuino en Burguillos. + + donde-comer + + reparto-a-domicilio-comida + pizzerias + + pizzeria-genuino + + Front door of 'Pizzería Genuino' + +

    Pizzería italiana Genuino, envío a domicilio en Burguillos.

    + +

    La Pizzería Genuino es ampliamente reconocida por los habitantes de Burguillos por la calidad de sus pizzas, se puede tanto comer en el establecimiento como pedir a domicilio.

    + +

    La ubicación de la pizzería es Calle Manuel Medina número 1, el número de teléfono para realizar pedidos es 672 128 822 y el horario es de 20:00-00:00 durante todos los días de la semana.

    + +

    Procedemos a dejaros la carta con los enlaces a la página web oficial de cada producto para que tengais siempre disponible la última información:

    + +

    Las más vendidas. Enlace oficial

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombreEnlaceIngredientesPrecio MedianaPrecio Grande
    4 FormaggiEnlaceTomate, mozzarella, brie, gorgonzola y grana padano8.00€17.00€
    CottoEnlaceTomate  mozzarella y jamón de york7.00€15.00€
    CarnivoraEnlaceTomate, mozzarella, criollo, frankfurt, bacon y jamón de york8.50€18.00€
    GolosaEnlaceMozzarella, champiñones, bacon y nata8.00€17.00€
    365EnlaceTomate, doble de mozzarella, chorizo, jamón de york y orégano8.00€17.00€
    Cotto e funghiEnlaceTomate, mozzarella, champiñones y jamón de york7.50€16.00€
    PiccantissimaEnlacePREGUNTAR8.50€18.00€
    Carbonara italianaEnlaceMozzarella, guanciale, pecorino romano, huevo y pimienta8.50€18.00€
    ChipsEnlaceTomate, mozzarella, frankfurt y patatas fritas7.50€16.00€
    + +

    Las más ligeras. Enlace oficial

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombreEnlaceIngredientesPrecio MedianaPrecio Grande
    Fresca frescaEnlaceTomate, tomate cherry, mozzarella fresca, aceitunas negras, rucula y grana padano8.50€18.00€
    ItaliaEnlaceMozzarella, tomate cherry, jamón serrano, rúcula y grana padano8.50€18.00€
    DelicataEnlaceMozzarella, calabacín y grana padano7.50€16.00€
    MeravigliosaEnlaceTomate, mozzarella, calabacín, tomate cherry y brie8.00€17.00€
    ParmigianaEnlaceTomate, mozzarella, berenjena y grana padano7.50€16.00€
    FunghiEnlaceTomate, mozzarella y champiñones7.00€15.00€
    + +

    A la italiana. Enlace oficial

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombreEnlaceIngredientesPrecio MedianaPrecio Grande
    MargheritaEnlaceTomate y mozzarella6.50€14.00€
    NapoliEnlaceTomate, mozzarella, anchoa, orégano7.50€16.00€
    SicilianaEnlaceTomate, anchoas, aceitunas negras, alcaparras y oréganoPREGUNTARPREGUNTAR
    RomanaEnlaceTomate, mozzarella, anchoas, alcaparras y orégano7.50€16.00€
    4 StagioniEnlaceTomate, mozzarella, champiñones, jamón de york, aceitunas negras y alcachofas8.50€18.00€
    CapricciosaEnlaceTomate, mozzarella, champiñones, jamón de york, aceitunas negras y alcachofas8.50€18.00€
    BufalaEnlaceTomate y mozzarella fresca8.00€17.00€
    BoscaiolaEnlaceTomate, mozzarella, criollo y champiñones7.50€16.00€
    + +

    A la Genuino. Enlace oficial

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombreEnlaceIngredientesPrecio MedianaPrecio Grande
    Nonna InaEnlaceTomate, mozzarella, criollo y gorgonzola7.50€16.00€
    GustosaEnlaceTomate, mozzarella, calabacín, bacon y nata8.00€17.00€
    ContadinaEnlaceTomate, mozzarella, criollo, cebolla morada y pimiento rojo8.00€17.00€
    Quinta del VillaEnlaceTomate, mozzarella, criollo, brie, tomate cherry y grana padano8.50€18.00€
    Quinta del ManuEnlaceTomate, mozzarella, criollo, chorizo, cebolla morada y grana padano8.50€18.00€
    AmatricianaEnlaceTomate, mozzarella, guanciale, cebolla morada, pecorino romano y pimienta8.50€18.00€
    + +

    Del mar. Enlace oficial

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombreEnlaceIngredientesPrecio MedianaPrecio Grande
    TonnoEnlaceTomate, mozzarella y atún7.50€16.00€
    Tonno e cipollaEnlaceTomate, mozzarella, atún y cebolla morada8.00€17.00€
    Tonno e carciofiniEnlaceTomate, mozzarella, atún y alcachofas8.00€17.00€
    Tonno y maisEnlaceTomate, mozzarella, atún, aceitunas negras y maiz8.00€17.00€
    NettunoEnlaceMozzarella, atún, tomate cherry y cebolla morada8.00€17.00€
    + +

    Especialidades. Enlace oficial

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombreEnlaceIngredientesPrecio SimplePrecio Completo
    Hot dog + bebidaEnlacePREGUNTAR4.00€4.50€
    Calzone liscioEnlaceTomate, mozzarella y jamón de yorkNO DISPONIBLE7.00€
    Calzone farcitoEnlaceTomate, mozzarella, jamón de york y champiñonesNO DISPONIBLE7.50€
    Calzone 4 formaggiEnlaceTomate, mozzarella, brie, gorgonzola y grana padanoNO DISPONIBLE8.00€
    Calzone NutellaEnlaceNutellaNO DISPONIBLE4.00€
    Pizzotto farcitoEnlaceMini calzone relleno al gustoNO DISPONIBLE4.00€
    + +

    Bebidas y cervezas. Enlace oficial

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombreEnlacePrecio
    Agua (500ml)Enlace1.00€
    Coca ColaEnlace1.50€
    Coca Cola ZeroEnlace1.50€
    Coca Cola Zero ZeroEnlace1.50€
    Fanta de naranjaEnlace1.50€
    Fanta de limónEnlace1.50€
    Aquarius de limónEnlace1.70€
    Aquarius de naranjaEnlace1.50€
    NesteaEnlace1.50€
    Coca Cola 2lEnlace2.50€
    Coca Cola Zero 2lEnlace2.50€
    Fanta naranja 2lEnlace2.50€
    Cruzcampo 250mlEnlace1.50€
    Cruzcampo 1lEnlace2.50€
    Tinto de veranoEnlace2.00€
    + +

    ¿Quieres ver tu negocio localizado en Burguillos en este espacio? Contacta con contact@owlcode.tech.

    +
    +
    diff --git a/content/posts/0000024-bar-restaurante-duran.xml b/content/posts/0000024-bar-restaurante-duran.xml new file mode 100644 index 0000000..cc55856 --- /dev/null +++ b/content/posts/0000024-bar-restaurante-duran.xml @@ -0,0 +1,668 @@ + + Burguillos.info + 2023-05-05T22:21+00:00 + Carta y Menú del Bar - Restaurante Durán - Centro de día en Burguillos. + Carta y Menú del Bar - Restaurante Durán - Centro de día en Burguillos. + + donde-comer + + hamburguesas + + bar-restaurante-duran + + Front door of 'Bar-Restaurante Durán - Centro de día' + +

    Información de contacto para preparación de pedidos.

    + +

    El Bar-Restaurante Durán - Centro de día, ubicado en avenida de Andalucía número 4 ofrece una propuesta única con sus platos de calidad excepcional.

    + +

    Os recomendamos probar los crepes de pollo, desde Burguillos.info los hemos probado y hemos quedado encantados por lo deliciosos que están.

    + +

    El teléfono de contacto es 604 404 294, se pueden pedir platos para recoger más adelante, pero por el momento no admiten pedidos a domicilio.

    + +

    Si deseas una salsa a parte la tendrás por 50 centimos extra.

    + +

    Procedemos a transcribir la carta a continuación:

    + +

    Aliños

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio tapaPrecio media raciónPrecio ración
    Ensaladilla2.50€5.00€7.50€
    Aliño de pulpo3.00€6.00€9.00€
    Aliño de hueva3.00€6.00€9.00€
    Salpicón de marisco3.00€6.00€9.00€
    Coctel de marisco---3.50€---
    Ensalada mixta---6.00€---
    Ensalada cesar---7.00€---
    Ensalada de la casa---7.50€---
    + +

    Guisos

    + + + + + + + + + + +
    NombrePrecio
    Carrillada4.00€
    + +

    Hamburguesas

    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio simplePrecio completa
    Pollo2.50€4.00€
    Buey3.50€7.00€
    Crujiente---6.00€
    Del Durán---7.50€
    + +

    Aperitivos

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio tapaPrecio media raciónPrecio ración
    Croquetas de pollo3.50€7.00€10.50€
    Croquetas de jamón3.50€7.00€10.50€
    Croquetas de gambas3.50€7.00€10.50€
    Variado de croquetas------11.00€
    Papas bravas2.50€5.00€7.50€
    Papas de la casa2.50€5.00€7.50€
    Papas alioli calientes2.50€5.00€7.50€
    Gratinadas 4 quesos con bacon------6.50€
    Gratinadas a la carbonara------6.50€
    Lagrimitas de pollo3.50€7.00€10.50€
    Tocinito3.00€6.00€9.00€
    Alitas a la barbacoa3.50€7.00€10.50€
    Bartolito3.50€7.00€10.50€
    Queso frito3.50€7.00€10.50€
    Taleguillas de queso3.50€7.00€10.50€
    Pollo al cajun4.00€8.00€12.00€
    + +

    Montaditos

    + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio
    Pollo o lomo2.50€
    Jamón y queso3.00€
    Melva con pimientos3.00€
    Gambas con alioli3.00€
    + +

    Carnes

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio tapaPrecio media raciónPrecio ración
    Carne asada3.00€6.00€9.00€
    Solomillo3.50€7.00€10.50€
    Pechuga3.00€6.00€---
    Pollo crujiente4.00€8.00€12.00€
    Tosta de solomillo4.00€8.00€12.00€
    Solomillo con queso y cebolla caramelizada3.50€7.00€10.50€
    Mini serranito pollo/lomo o tortilla---3.50€4.00€
    Serranito pollo/lomo o tortilla---5.00€5.50€
    Berenjena rellena------4.50€
    Solomillo de pavo------7.00€
    Churrasco de cerdo------7.00€
    Brocheta de solomillo------7.00€
    Cachopo------7.00€
    Solomillo mostaza crujiente------7.00€
    (Salsa a elejir) Alioli, mojo picón, verde, carbonara, roque y whisky
    + +

    Pescados

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio tapaPrecio media raciónPrecio ración
    Adobo3.50€7.00€10.50€
    Boquerones3.50€7.00€10.50€
    Chipirón plancha o frito3.50€7.00€10.50€
    Chocos fritos3.50€7.00€10.50€
    Brocheta de marisco------5.50€
    Lomito de merluza------4.50€
    Solomillo de atún------4.50€
    Pez espada------10.00€
    Merluza a la marinera------6.50€
    Choco a la plancha------10.50€
    Pulpo a la gallega------8.00€
    Cazuela de gulas, chipirones, almejas y langostinos------8.00€
    Gambas al ajillo------8.00€
    Saquito de gambas------5.00€
    + +

    Panes

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio
    Gambas y alioli6.00€
    Salmorejo y bacalao7.00€
    Gordi (Mojo Picón)7.00€
    Salmorejo y jamón5.00€
    Chicharrón de Cádiz y queso7.00€
    Queso de rulo, bacon y nueces7.00€
    Gulas y huevos de codorniz8.00€
    + +

    Revuelto

    + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio
    Bacalao dorado7.50€
    Gulas y langostinos7.50€
    Morcilla de arroz y piñones7.00€
    Huevos rotos con gulas y langostinos8.00€
    + +

    Sugerencias

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio
    Crepes de carrilla4.00€
    Crepes de pollo4.00€
    Champiñones rellenos4.00€
    Conos de langostinos4.00€
    Fideos tostados4.00€
    Solomillo mozárabe3.50€
    Rollitos serranos3.50€/7.00€
    Perrito del kiki4.50€
    Torre serrana3.50€
    Cazuela de chipirón, langostinos, gulas y almejas7.50€
    Queso frito, boquerones y salmorejo4.00€
    Patatas arrieras6.00€
    Tabla de queso frito8.00€
    Morcilla crocante4.00€
    Donut de queso4.50€
    + +

    Para los peques

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio tapaPrecio media raciónPrecio ración
    Perritos------3.50€
    Nuggets3.50€7.00€10.50€
    Mini hamburguesas------3.50€
    + +

    Postres

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio
    Coulant de chocolate4.00€
    Gofres2.50€
    Gofres + helado3.50€
    Gofres especial chocolate4.00€
    Crepes2.50€
    Crepes + helado3.50€
    Crepes especial chocolate4.00€
    Tartas caseras2.50€
    Brownei de galleta4.00€
    Torrija caramelizada4.00€
    Batidos helado (Sabores a elegir)4.00€
    + +

    ¿Quieres ver tu negocio localizado en Burguillos en este espacio? Contacta con contact@owlcode.tech.

    +
    +
    diff --git a/content/posts/0000025-bar-cafe-beluche.xml b/content/posts/0000025-bar-cafe-beluche.xml new file mode 100644 index 0000000..61ab60c --- /dev/null +++ b/content/posts/0000025-bar-cafe-beluche.xml @@ -0,0 +1,322 @@ + + Burguillos.info + 2023-05-06T15:33+00:00 + Carta y Menú del Café - Bar Beluche en Burguillos. + Carta y Menú del Café - Bar Beluche en Burguillos. + + donde-comer + + hamburguesas + reparto-a-domicilio-comida + + cafe-bar-beluche + + Front door of 'Café-Bar Beluche' + +

    Información de contacto para preparación de pedidos y envío a domicilio.

    + +

    El Café - Bar Beluche es uno de los lugares favoritos de los habitantes de Burguillos para comer o simplemente tomar un refresco o un café.

    + +

    Su ubicación en calle Albahaca número 13 es inmejorable, ofreciendo terrazas a parte de mesas en el interior.

    +

    Los teléfonos de contacto son 694 200 713 y 691 492 054, puedes usarlos para reservar, pedir comida a domicilio o pedir que te preparen platos para llevar.

    + +

    Procedemos a transcribir la carta a continuación:

    + +

    Ensaladas

    + + + + + + + + + + + + + + +
    NombrePrecio
    Mixta6.00€
    César6.50€
    + + +

    Revueltos

    + + + + + + + + + + + + + + +
    NombrePrecio
    Gula langostinos7.50€
    Bacalao dorado7.50€
    + +

    Para compartir

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio tapaPrecio plato
    Papas bravas3.00€5.50€
    Papas de mi prima3.50€6.00€
    Papas arrieras3.80€6.50€
    Bartolitos. (Langostinos con bacon)3.80€6.00€
    Queso rulo con bacon, nueces y miel de caña3.80€6.00€
    Morcilla crocanti3.50€6.00€
    Muss de pato4.00€8.00€
    Duo de rulo y muss de pato---7.00€
    Talegitas de queso3.50€6.00€
    Champiñones con alioli y jamón3.50€6.50€
    Fideos tostados---4.00€
    Variado de croquetas---11.00€
    + +

    Rico rico

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio tapaPrecio plato
    Pastel de berenjenas---3.50€
    Timbal de arroz con chipirones y alioli4.00€7.50€
    Gambas al ajillo---7.50€
    Flauta de jamón york y queso3.00€6.00€
    Saquitos de gambas y salsa de mango---4.80€
    Medallones de solomillo. (Roque, whisky, mojo)3.50€6.50€
    Solomillo rulo de queso y miel de caña4.00€7.50€
    Carrillada ibérica3.50€7.00€
    Pollo bechamel3.60€6.50€
    Pollo kentucky---3.50€
    + +

    Pescados

    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio tapaPrecio plato
    Chipirones3.90€7.50€
    Pez espada---12.00€
    Merluza confitada---7.50€
    Bacalao confitado---9.00€
    + +

    Carnes

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio tapaPrecio plato
    Solomillo ibérico---12.00€
    Presa ibérica---14.00€
    Pluma ibérica---13.00€
    Presa con mostaza4.00€8.00€
    Solomillo de pavo---9.00€
    Medallones de solomillo3.50€6.50€
    Hamburguesa de buey---5.50€
    Abanico ibérico---11.00€
    Mini hamburguesa---2.50€
    Montadito de pollo o lomo---2.50€
    Mini de pollo o lomo---3.50€
    Serranito---5.50€
    Montadito de gambas con alioli---3.20€
    + +

    Postres

    + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio
    Gofres con nata y chocolate3.50€
    Tortitas americanas3.80€
    Tartas (Porción)3.50€
    Coulant con helado de vainilla4.00€
    + +

    ¿Quieres ver tu negocio localizado en Burguillos en este espacio? Contacta con contact@owlcode.tech.

    +
    +
    diff --git a/content/posts/0000026-pizzeria-pepin.xml b/content/posts/0000026-pizzeria-pepin.xml new file mode 100644 index 0000000..60f0eca --- /dev/null +++ b/content/posts/0000026-pizzeria-pepin.xml @@ -0,0 +1,409 @@ + + Burguillos.info + 2023-05-06T22:14+00:00 + Carta y Menú de la Pizzería - Hamburguesería - Baguetería Pepín + Carta y Menú de la Pizzería - Hamburguesería - Baguetería Pepín + + donde-comer + + hamburguesas + pizzerias + reparto-a-domicilio-comida + + pizzeria-pepin + + Front door of 'Pizzería - Hamburguesería - Baguetería Pepín' + +

    Información de contacto para preparación de pedidos y envío a domicilio.

    + +

    La Pizzería - Hamburguesería - Baguetería Pepín.- Ubicada en calle Los Álamos número 13.- Es el lugar perfecto para una comida en familia o con amigos, además tienes la posibilidad de realizar tu pedido a domicilio.

    + +

    El teléfono de contacto para los pedidos a domicilio es 692 149 337.

    + +

    Procedemos a transcribir la carta a continuación:

    + +

    Pizzas.

    + +

    Por el precio indicado en la carta puedes pedir una pizza con dos ingredientes, a partir del tercero el precio se incrementa de esta forma:

    + +

    Precio ingredientes.

    + + + + + + + + + + + + + + + + + + +
    Tipo de pizzaIncremento de precio por ingrediente extra
    Pequeña0.50€
    Mediana0.60€
    Grande0.70€
    + +

    Tabla de precios pizzas.

    + +

    Las siguientes ofertas aplican al precio de las pizzas, si pides dos medianas te sale por 10€, mientras que si pides dos grandes por 17€. Ademas una pizza grande con 6 o más ingredientes te permite tener una pizza extra pequeña de forma gratuíta.

    + + + + + + + + + + + + + + + + + + +
    Tipo de pizzaPrecio
    Pequeña4.00€
    Mediana5.50€
    Grande9.00€
    + +

    Ingredientes a escoger.

    + +
      +
    • Jamón york.
    • +
    • Roquefort.
    • +
    • Chorizo.
    • +
    • Salchicha.
    • +
    • Gambas.
    • +
    • Aceitunas.
    • +
    • Jamón.
    • +
    • Cebolla.
    • +
    • Bacon.
    • +
    • Maíz.
    • +
    • Piña.
    • +
    • Pimiento rojo.
    • +
    • Pimiento verde.
    • +
    • Pepinillo.
    • +
    • Huevo.
    • +
    • Champiñones.
    • +
    • Anchoas.
    • +
    • Atún.
    • +
    • Carne.
    • +
    • Salsa barbacoa.
    • +
    • Salsa carbonara.
    • +
    • Ternera.
    • +
    • Peperoni.
    • +
    • Cheddar.
    • +
    + +

    Hamburguesas.

    + +

    Hamburguesas sin menú.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombreIngredientesPrecio
    Hamburguesa de Buey---5.00€
    NormalCarne y queso1.50€
    SabrosaCarne, bacon, cebolla y queso2.50€
    SúperDos carnes, lechuga, tomate, cebolla y queso2.80€
    CompletaCarne, huevo, lechuga, tomate, cebolla y queso2.50€
    DipoFilete de pollo, lechuga, tomate, cebolla y queso2.50€
    JomiCarne, cochinito, tomate, pepinillo y queso2.50€
    Crujiente de pollo---4.50€
    Perrito caliente---2.50€
    Nuggets---2.80€
    + +

    Hamburguesas con menú.

    + +

    Todos los menús incluyen patatas y refresco.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio
    Mini menú (Hamburguesa Normal)3.60€
    Mega menú (Hamburguesa Completa)4.60€
    Menú Sabrosa4.60€
    Menú Dipo4.60€
    Menú Jomi4.60€
    Menú Nuggets4.80€
    Menú Perrito4.60€
    Super Menú4.90€
    + +

    Baguettes.

    + +

    Baguettes sin menú.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio
    Cochinito3.00€
    Tortilla de patatas3.00€
    Bacon y queso3.00€
    Jamón y queso3.00€
    Tortilla francesa2.80€
    Pollo y lechuga3.70€
    Vegetal3.00€
    Filete de lomo3.70€
    Chorizo y roquefort2.50€
    Atún y pimiento3.00€
    Pollo y vegetal3.90€
    + +

    Baguettes con menú.

    + +

    Los menús incluyen patatas y refresco.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio
    Cochinito4.80€
    Bacon4.80€
    Vegetal4.80€
    Atún y pimientos4.80€
    Chorizo y roquefort4.30€
    Pollo y lechuga5.00€
    Pollo y vegetal5.60€
    Tortilla de patatas4.80€
    Tortilla francesa4.70€
    Lomo5.50€
    Jamón y queso4.80€
    + +

    Complementos

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NombrePrecio
    Palomitas de queso4.50€
    Croquetas de jamón3.00€
    Churrasco de cerdo5.00€
    Pechuga de pollo5.00€
    Cartucho de patatas fritas pequeño1.00€
    Cartucho de patatas fritas grande2.00€
    Serranito de lomo o pollo4.00€
    Patatas bravas3.00€
    Montadito de pollo3.00€
    Patatas gratinadas con bacon y cheddar4.00€
    Salsa a elegir (Mojo picón, alioli, barbacoa)0.40€
    + +

    Ensaladas

    + + + + + + + + + + + + + + + + + +
    NombreIngredientesPrecio
    MixtaLechuga, tomate, cebolla y huevo3.00€
    EspecialLechuga, tomate, huevo, atún, cebolla, jamón york y piña4.00€
    + +

    Bebidas

    + + + + + + + + + + + + + + +
    TipoPrecio
    Cerveza o zumo1.00€
    Refresco1.20€
    + +

    ¿Quieres ver tu negocio localizado en Burguillos en este espacio? Contacta con contact@owlcode.tech.

    +
    +
    diff --git a/content/posts/0000027-guillena-adopta-sonrisas.xml b/content/posts/0000027-guillena-adopta-sonrisas.xml new file mode 100644 index 0000000..4200045 --- /dev/null +++ b/content/posts/0000027-guillena-adopta-sonrisas.xml @@ -0,0 +1,20 @@ + + Burguillos.info + 2023-05-08T22:14:00+02:00 + Jornada de puertas abiertas "Guillena con el pueblo saharaui". + Jornada de puertas abiertas "Guillena con el pueblo saharaui". + index + + sahara-acogida-ninos + + Transcript: Jornada de puertas abiertas Guillena adopta sonrisas. (Guillena con el pueblo saharahui) + +

    Acogida urgente de niños saharauis, se buscan familias de Sevilla, Burguillos, Alcalá del río, Castilblanco de los arroyos, la Rinconada, Guillena.

    + +

    La asociación "Guillena con el pueblo saharaui" organiza una jornada de puertas abiertas en Guillena calle Manuel Romero Romero número 1 el día 12 de Mayo de 2023 a las 20:30.

    + +

    Estáis invitados a asistir, por otro lado se informa de la necesidad urgente de familias dispuestas a acoger de forma temporal a niños saharauis, contactad con este email guillenaconelpueblosaharaui@gmail.com para recibir toda la información si estais dispuestos a acoger a uno de estos niños.

    + +

    Se actualizará con más información este artículo en los próximos días.

    +
    +
    diff --git a/content/posts/0000028-hamburgueseria-la-ermita.xml b/content/posts/0000028-hamburgueseria-la-ermita.xml new file mode 100644 index 0000000..acdf172 --- /dev/null +++ b/content/posts/0000028-hamburgueseria-la-ermita.xml @@ -0,0 +1,198 @@ + + Burguillos.info + 2023-05-12T14:03+00:00 + 2023-06-06T15:06+00:00 + Carta y Menú de la Hamburguesería la Ermita + Carta y Menú de la Hamburguesería la Ermita + + donde-comer + + hamburguesas + pizzerias + reparto-a-domicilio-comida + + hamburgueseria-la-ermita + +

    Ahora aceptan pedidos a domicilio.

    + Front door of 'Hamburguesería la Ermita' + +

    Información de contacto para preparación de pedidos.

    + +

    (Parrafo actualizado tras la cata del equipo de Burguillos.info) La hamburguesería la Ermita es un restaurante de nueva apertura, sus hamburguesas son de una calidad excelente, los tiempos de espera para la preparación son cortos y cuídan hasta el mínimo detalle.

    + +

    Su localización es calle Cádiz número 3 y su número de teléfono para la preparación de pedidos y envío a domicilio es 682 283 189.

    + +

    Procedemos a listar la carta.

    + +

    Entrantes.

    + +
      +
    • Chili Cheese Bite 3€ tapa.
    • +
    • Fingers de mozarella 3€ tapa.
    • +
    • Aros de cebolla 3€ tapa.
    • +
    • Nuggets 3€ tapa.
    • +
    • Crujientes de pollo 3€ tapa.
    • +
    • Lagrimitas 3€ tapa.
    • +
    • Croquetas de jamón / queso azul y cebolla caramelizada / pizza 3€ tapa.
    • +
    • Patatas alioli 2.50€ tapa 4€ plato.
    • +
    • Ensaladilla 2.50€ tapa 4€ plato.
    • +
    + +

    Pizzas.

    + +

    Todas las pizzas vienen con 2 ingredientes incluidos en el precio, por 0.60€ puedes añadir un ingrediente extra o una salsa extra por 0.30€.

    + +

    Tienes la posibilidad de pedir una pizza mediana nutella por 5.50€ desde Burguillos.info suponemos que no se permiten + otros ingredientes para evitar aberraciones gastronómicas.

    + +

    Tamaño de pizza.

    + +
      +
    • Mediana 5.50€.
    • +
    • Grande 9.00€.
    • +
    + +

    Ingredientes disponibles.

    + +
      +
    • Jamón York
    • +
    • Bacon
    • +
    • Salchicha
    • +
    • Pepperoni
    • +
    • Roquefort
    • +
    • Jamón
    • +
    • Barbacoa
    • +
    • Atún
    • +
    • Cebolla
    • +
    • Pimientos
    • +
    • Gambas
    • +
    • Huevo
    • +
    • Aceitunas
    • +
    • Pepinillos
    • +
    • Champiñones
    • +
    • Maíz
    • +
    • Piña
    • +
    • Anchoa
    • +
    • Rulo de cabra
    • +
    • Rúcula
    • +
    • Tomate natural
    • +
    • Carbonara
    • +
    • Carne kebab
    • +
    • Pollo asado y salsa kebab
    • +
    • 4 quesos
    • +
    + +

    Bebidas.

    + +
      +
    • Refresco 1.50€
    • +
    • Cerveza de barril 1.80€
    • +
    • Pitufo (3/4) 1.80€
    • +
    • Tinto 1.50€
    • +
    • Radler 1.80€
    • +
    • Cerveza sin botellín 1.20€ 3/4 1.80€
    • +
    • Litro 2.20€
    • +
    • Agua pequeña 0.80€
    • +
    • Agua grande 1.20€
    • +
    • Zumo 1.00€
    • +
    • Café e infusión 1.20€
    • +
    • Combinado 4.50€
    • +
    + +

    Helados.

    + +
      +
    • Sandy 2.20€
    • +
    • Mini Sandy 1.50€
    • +
    • Mix Sandy 3.20€
    • +
    • Mini Mix Sandy 2.50€
    • +
    • Batido pequeño 2.50€
    • +
    • Batido grande 3.20€
    • +
    + +

    Bocadillos.

    + +
      +
    • Tortilla 3.00€
    • +
    • Cochinito 3.00€
    • +
    • Lomo adobado 3.00€
    • +
    • Bacon y queso 3.00€
    • +
    • Atún y pimiento 3.00€
    • +
    • Carne mechada y chimichurri 3.50€
    • +
    • Filete de lomo, mayonesa y lechuga 3.50€
    • +
    • Serranito de pollo o cerdo 4.50€
    • +
    + +

    Montaditos.

    + +
      +
    • Gambas alioli 2.50€
    • +
    • Melva con pimiento 2.50€
    • +
    • Carne mechada con chimichurri 2.50€
    • +
    • Solomillo (Whisky, roquefort o pimienta) 2.50€
    • +
    • Pollo o lomo 2.50€
    • +
    + +

    Perritos.

    + +
      +
    • Simple (Salchicha + salsa) 2.00€
    • +
    • Completo (Salchicha, cebolla frita, zanahoria, patatas paja y salsa) 2.50€
    • +
    + +

    Carnes.

    + +
      +
    • Pechuga y patatas 5€ plato.
    • +
    • Churrasco y patatas 5€ plato.
    • +
    • Solomillo (Whisky, roquefort o pimienta) 3.00€ tapa 5.00€ plato.
    • +
    + +

    Patatas gratinadas.

    + +

    En formato pequeño cuestan 4.00€ y en formato grande 6.00€, a elegir entre las siguientes combinaciones.

    + +
      +
    • Alioli + queso + bacon.
    • +
    • Salsa cheedar + bacon + cebolla frita.
    • +
    • Salsa kebab + carne kebab.
    • +
    + +

    Patatas normales.

    + +
      +
    • Pequeñas 1.00€
    • +
    • Grandes 1.50€
    • +
    • Gajo grande 1.50€
    • +
    • Cris Criss - Cross grande 2.00€
    • +
    + +

    Hamburguesas.

    + +

    Puedes solicitar un extra en salsa por 0.30€.

    + +
      +
    • Solo carne 1.50€.
    • +
    • Solo queso 2.00€.
    • +
    • BBQ (Carne, salsa barbacoa, queso y pepinillo) 2.50€.
    • +
    • Texas (Carne, salsa barbacoa, queso y aros de cebolla) 2.50€.
    • +
    • Cheedar simple (Carne, salsa cheedar, tomate, cebolla frita) 2.50€.
    • +
    • Salad (Carne, mayonesa, lechuga y tomate) 2.50€.
    • +
    • Porky (Carne cerdo, bacon, salsa bacon, queso, tomate, cebolla frita) + patatas 6.50€.
    • +
    • Roquefort (Carne mixta, salsa roquefort, lechuga, tomate, queso granapadano, bacon y cebolla frita) + patatas 6.50€.
    • +
    • Campera (Pollo campero, mayonesa, lechuga, tomate, queso y bacon) + patatas 6.50€.
    • +
    • Miel y mostaza (Carne mixta, rúcula, tomate, cebolla caramelizada, queso gouda, bacon, salsa miel y mostaza) + patatas 6.50€.
    • +
    • Boletus (Carne mixta, queso gouda, bacon, champiñones y salsa boletus) + patatas 6.50€.
    • +
    • La Ermita (Carne retinto, salsa barbacoa especial, tomate, cebolla frita, rulo de cabra y bacon) + patatas 7.50€.
    • +
    • Cabrales (Carne mixta, salsa cabrales, gouda, bacon, lechuga, tomate y queso) + patatas 6.50€.
    • +
    • Cheedar (Carne mixta o pollo empanado, salsa cheedar, cebolla frita, tomate, queso y bacon) + patatas 6.50€.
    • +
    • Completa (Carne mixta, mayonesa, lechuga, cebolla frita, tomate, pepinillo y cebolla) + patatas 6.50€.
    • +
    • Huevo (Carne mixta, mayonesa, lechuga, cebolla frita, tomate, queso, huevo y bacon) + patatas 6.50€.
    • +
    • Steak (Carne mixta, mayonesa, lechuga, tomate, queso, bacon y salsa bbq) + patatas 6.50€.
    • +
    • Cheese bacon (Carne mixta, queso, bacon, pepinillo, ketchup, mostaza y cebolla) + patatas 6.50€.
    • +
    • Romana (Carne mixta, salsa bbq, lechuga, tomate, queso y aros de cebolla) + patatas 6.50€.
    • +
    + +

    ¿Quieres ver tu negocio localizado en Burguillos en este espacio? Contacta con contact@owlcode.tech.

    +
    +
    diff --git a/extract_carta_genuino.pl b/extract_carta_genuino.pl new file mode 100644 index 0000000..2ebe98b --- /dev/null +++ b/extract_carta_genuino.pl @@ -0,0 +1,56 @@ +#!/usr/bin/env perl + +use v5.36.0; + +use strict; +use warnings; + +use utf8; + +use Mojo::UserAgent; + +my $ua = Mojo::UserAgent->new; +my $base_url = "https://www.mundogenuino.eu"; +my $dom = $ua->get($base_url)->result->dom; +my $category_anchors = $dom->find('a.s123-fast-page-load'); +binmode STDOUT, ':utf8'; +for my $category_anchor ($category_anchors->each) { + my $title_category = $category_anchor->all_text; + my $url_category = $base_url . $category_anchor->attr('href'); + next unless $title_category; + $title_category =~ s/^\s+//; + $title_category =~ s/\s+$//; + say "$title_category"; + say "$url_category"; + my $dom_category = $ua->get($url_category)->result->dom; + my @product_containers = $dom_category->find('a.article-container')->each; + for my $product_container (@product_containers) { + my $url_product = $base_url.$product_container->attr('href'); + my $product_title = $product_container->at('h4')->all_text; + my $dom_product = $ua->get($url_product)->result->dom; + my $ingredients_tag = $dom_product->at('strong'); + my $ingredients = ''; + if (defined $ingredients_tag) { + $ingredients = $ingredients_tag->all_text; + } + my @prices; + my $i = 0; + my $product_text = $dom_product->all_text; + while ($product_text =~ /(\S+(\s*)€)/ug) { + my $price = $1; + $price =~ s/,/./g; + $price =~ s/\s//g; + push @prices, $price; + last if ++$i == 2; + } + if (!scalar @prices) { + my ($price) = $product_text =~ /(\d+,\d{2})(?:\s|$)/; + if (defined $price) { + $price =~ s/,/./g; + push @prices, $price.'€'; + } + } + say join '', map { "($_)" } $product_title, $url_product, $ingredients, @prices; + } + # say join "\n", $dom_category->find('h4')->map('all_text')->each; +} diff --git a/generate_pass.pl b/generate_pass.pl new file mode 100644 index 0000000..b838dd2 --- /dev/null +++ b/generate_pass.pl @@ -0,0 +1,16 @@ +#!/usr/bin/env perl + +use v5.36.0; +use strict; +use warnings; + +use Crypt::URandom qw/urandom/; +use Crypt::Bcrypt qw/bcrypt bcrypt_check/; + +my $new_password = urandom(50); +my $new_salt = urandom(16); +$new_password = unpack 'H*', $new_password; + +say "This is your password: ($new_password)"; +say "This is bcrypted: (@{[bcrypt $new_password, '2b', 12, $new_salt]})"; + diff --git a/js-src/index.ts b/js-src/index.ts new file mode 100644 index 0000000..a2228dd --- /dev/null +++ b/js-src/index.ts @@ -0,0 +1,29 @@ +"use strict"; +import Tablesort from 'tablesort'; +window.Tablesort = require('tablesort'); +require('tablesort/src/sorts/tablesort.number'); + +window.onload = () => { + const menu_expand = document.querySelector('a.menu-expand'); + const mobile_foldable = document.querySelector('nav.mobile-foldable'); + const tables = document.querySelectorAll('table') + + if (menu_expand !== null && mobile_foldable !== null) { + menu_expand.addEventListener('click', () => { + mobile_foldable.classList.toggle('show'); + }); + } + + for (const table of tables) { + const header = table.querySelector('tr'); + if (header !== null) { + header.setAttribute('data-sort-method', 'none') + for (const th of header.querySelectorAll('th')) { + if (th.getAttribute('data-sort-method') == null) { + th.setAttribute('data-sort-method', 'thead') + } + } + } + new Tablesort(table) + } +}; diff --git a/lib/BurguillosInfo.pm b/lib/BurguillosInfo.pm index 2c1d4c2..2f04c93 100644 --- a/lib/BurguillosInfo.pm +++ b/lib/BurguillosInfo.pm @@ -19,21 +19,30 @@ sub startup ($self) { ); my $config = $self->plugin('JSONConfig'); $self->config( - hypnotoad => { proxy => 1, listen => ['http://localhost:3000'] } ); - $self->secrets($self->config->{secrets}); + hypnotoad => { proxy => 1, listen => [$self->config('listen') // 'http://localhost:3000'] } ); + $self->config( css_version => int( rand(10000) ) ); + $self->secrets( $self->config->{secrets} ); # Router my $r = $self->routes; # Normal route to controller $r->get('/')->to('Page#index'); + $r->get('/sitemap.xml')->to('Sitemap#sitemap'); + $r->get('/robots.txt')->to('Robots#robots'); + $r->get('/aprende-a-dibujar-con-krita')->to('Page#rickroll'); # $r->get('/:post')->to('Page#post'); $r->get('/stats')->to('Metrics#stats'); $r->get('/<:category>.rss')->to('Page#category_rss'); + $r->get('/:category_slug/atributo/<:attribute_slug>-preview.png')->to('Attribute#get_attribute_preview'); + $r->get('/:category_slug/atributo/:attribute_slug')->to('Attribute#get'); + $r->get('/<:category>-preview.png')->to('Page#get_category_preview'); $r->get('/:category')->to('Page#category'); $r->get('/posts/<:slug>-preview.png')->to('Page#get_post_preview'); $r->get('/posts/:slug')->to('Page#post'); + $r->get('/filtros')->to('Filter#list'); + $r->get('/filtros/:slug')->to('Filter#get'); $r->get('/stats/login')->to('Metrics#login'); $r->post('/stats/login')->to('Metrics#submit_login'); } diff --git a/lib/BurguillosInfo/Categories.pm b/lib/BurguillosInfo/Categories.pm index d7801d2..b95e66b 100644 --- a/lib/BurguillosInfo/Categories.pm +++ b/lib/BurguillosInfo/Categories.pm @@ -5,10 +5,14 @@ use v5.34.1; use strict; use warnings; +use feature 'signatures'; + use Const::Fast; use Mojo::DOM; use Path::Tiny; +use BurguillosInfo::Preview; + const my $CURRENT_FILE => __FILE__; const my $CATEGORIES_DIR => path($CURRENT_FILE)->parent->parent->parent->child('content/categories'); @@ -19,7 +23,7 @@ sub new { return bless {}, shift; } -sub Retrieve { +sub Retrieve($self) { if ( defined $cached_categories ) { return $cached_categories; } @@ -28,26 +32,100 @@ sub Retrieve { warn "Bad file $category_file, omiting...", next if !-f $category_file || $category_file !~ /\.xml$/; my $dom = Mojo::DOM->new( $category_file->slurp_utf8 ); - my $title = $dom->at(':root > title')->text + defined(my $title = $dom->at(':root > title')->text) or die "Missing title at $category_file."; - my $description = $dom->at(':root > description')->content + defined(my $description = $dom->at(':root > description')->content) or die "Missing description at $category_file"; - my $slug = $dom->at(':root > slug')->text + defined(my $slug = $dom->at(':root > slug')->text) or die "Missing slug at $category_file"; - my $menu_text = $dom->at(':root > menu_text')->content + defined (my $menu_text = $dom->at(':root > menu_text')->content) or die "Missing menu_text at $category_file"; defined (my $priority = $dom->at(':root > priority')->text) or die "Missing priority at $category_file"; + my $attributes = $self->_GetAttributes($dom, $category_file); + my $parent_tag = $dom->at(':root > parent'); + my $parent; + if (defined $parent_tag) { + $parent = $parent_tag->content; + } my $category = { title => $title, menu_text => $menu_text, slug => $slug, description => $description, priority => $priority, + ( + (defined $parent) ? + (parent => $parent) : + () + ), + attributes => $attributes, }; $cached_categories->{$slug} = $category; } + $self->_AvoidGrandChildCategories($cached_categories); + $self->_PopulateChildrenField($cached_categories); return $cached_categories; } +sub _GetAttributes($self, $dom, $category_file) { + my $attributes_tag = $dom->at(':root > attributes'); + my %attributes; + if (defined $attributes_tag) { + my @attribute_tag_list = $attributes_tag->find('attributes > attribute')->each; + for my $attribute_tag (@attribute_tag_list) { + defined (my $menu_text = $attribute_tag->at('attribute > menu_text')->content) + or die "Missing attribute menu_text at $category_file"; + defined (my $description = $attribute_tag->at('attribute > description')->content) + or die "Missing attribute description at $category_file"; + defined (my $title = $attribute_tag->at('attribute > title')->text) + or die "Missing attribute title at $category_file"; + defined (my $identifier = $attribute_tag->at('attribute > identifier')->text) + or die "Missing attribute identifier at $category_file"; + defined (my $priority = $attribute_tag->at('attribute > priority')->text) + or die "Missing attribute priority at $category_file"; + $attributes{$identifier} = { + title => $title, + identifier => $identifier, + priority => $priority, + menu_text => $menu_text, + description => $description, + }; + } + } + return \%attributes; +} + +sub _PopulateChildrenField($self, $categories) { + for my $category_name (keys %$categories) { + my $category = $categories->{$category_name}; + $category->{children} //= []; + my $parent_name = $category->{parent}; + if (!defined $parent_name) { + next; + } + my $parent = $categories->{$parent_name}; + if (!defined $parent) { + die "Category $parent not exists and is the parent of $category_name."; + } + $parent->{children} //= []; + push $parent->{children}->@*, $category; + } +} + +sub _AvoidGrandChildCategories($self, $categories) { + for my $category_slug (keys %$categories) { + my $category = $categories->{$category_slug}; + my $parent = $category->{parent}; + if (defined $parent && defined $categories->{$parent}{parent}) { + die "$category_slug category is grandchild of $categories->{$parent}{parent}) category and this is not allowed."; + } + } +} + +sub PreviewOg($self, $category) { + my $title = $category->{title}; + my $description = $category->{description}; + return BurguillosInfo::Preview->Generate($title, $description, undef); +} 1; diff --git a/lib/BurguillosInfo/Controller/Attribute.pm b/lib/BurguillosInfo/Controller/Attribute.pm new file mode 100644 index 0000000..4477631 --- /dev/null +++ b/lib/BurguillosInfo/Controller/Attribute.pm @@ -0,0 +1,66 @@ +package BurguillosInfo::Controller::Attribute; +use v5.34.1; + +use strict; +use warnings; + +use Data::Dumper; + +use BurguillosInfo::Categories; + +use Mojo::Base 'Mojolicious::Controller', -signatures; + +use BurguillosInfo::Preview; + +sub get_attribute_preview ($self) { + my $category_slug = $self->param('category_slug'); + my $attribute_slug = $self->param('attribute_slug'); + my $categories = BurguillosInfo::Categories->new->Retrieve; + my $category = $categories->{$category_slug}; + if ( !defined $category ) { + return $self->reply->not_found; + } + my $attribute = $category->{attributes}{$attribute_slug}; + if ( !defined $attribute ) { + return $self->reply->not_found; + } + + $self->render( + format => 'png', + data => BurguillosInfo::Preview->Generate( + $attribute->{title}, $attribute->{description}, undef + ), + ); +} + +sub get ($self) { + my $category_slug = $self->param('category_slug'); + my $attribute_slug = $self->param('attribute_slug'); + + my $categories = BurguillosInfo::Categories->new->Retrieve; + my $category = $categories->{$category_slug}; + if ( !defined $category ) { + return $self->reply->not_found; + } + my $attribute = $category->{attributes}{$attribute_slug}; + if ( !defined $attribute ) { + return $self->reply->not_found; + } + my $posts = BurguillosInfo::Posts->RetrieveDirectPostsForCategory( + $category->{slug} ); + $posts = [ grep { defined $_->{attributes}{$attribute_slug} } @$posts ]; + my $base_url = $self->config('base_url'); + $self->render( + template => 'page/attribute', + category => $category, + attribute => $attribute, + categories => $categories, + posts => $posts, + ogimage => $base_url . '/' + . $category->{slug} + . '/atributo/' + . $attribute->{identifier} + . '-preview.png', + ); +} +1; diff --git a/lib/BurguillosInfo/Controller/Metrics.pm b/lib/BurguillosInfo/Controller/Metrics.pm index ac010a7..2d0ebd2 100644 --- a/lib/BurguillosInfo/Controller/Metrics.pm +++ b/lib/BurguillosInfo/Controller/Metrics.pm @@ -9,7 +9,7 @@ use Data::Dumper; use BurguillosInfo::Tracking; -use Mojo::Base 'Mojolicious::Controller'; +use Mojo::Base 'Mojolicious::Controller', '-signatures'; use DateTime::Format::ISO8601; use DateTime::Format::Mail; @@ -37,7 +37,27 @@ sub stats { } my $data = $tracking->get_global_data($self); my $data_per_url = $tracking->get_data_for_urls($self); - $self->render(tracking_data => $data, tracking_by_url => $data_per_url); + my $google_data = $tracking->get_google_data($self); + $self->_filter_data_per_url($data_per_url); + $self->_filter_data_per_url($google_data); + $self->render(tracking_data => $data, tracking_by_url => $data_per_url, google_data => $google_data); +} + +sub _filter_data_per_url($self, $data_per_url) { + my $filter = $self->param('filter'); + if (!defined $filter) { + return; + } + my @new_data_per_url; + if ($filter eq 'remove-extensions') { + for my $url (@$data_per_url) { + if ($url->{path} =~ /\.\w+$/) { + next; + } + push @new_data_per_url, $url; + } + } + @$data_per_url = @new_data_per_url; } sub submit_login { diff --git a/lib/BurguillosInfo/Controller/Page.pm b/lib/BurguillosInfo/Controller/Page.pm index 4768e76..939eab9 100644 --- a/lib/BurguillosInfo/Controller/Page.pm +++ b/lib/BurguillosInfo/Controller/Page.pm @@ -10,7 +10,7 @@ use BurguillosInfo::Posts; use Data::Dumper; -use Mojo::Base 'Mojolicious::Controller'; +use Mojo::Base 'Mojolicious::Controller', '-signatures'; use DateTime::Format::ISO8601; use DateTime::Format::Mail; @@ -27,6 +27,14 @@ sub index { ); } +sub rickroll($self) { + if ($self->req->headers->user_agent =~ /bot/i) { + return $self->render(text => ''); + } + $self->res->headers->location('http://ibaillanos.tv'); + $self->render(text => '', status => 302); +} + sub category_rss { my $self = shift; my $categories = BurguillosInfo::Categories->new->Retrieve; @@ -64,7 +72,7 @@ sub category_rss { 'Todas las noticias de la categoria de Burguillos.info ' . $category->{title} ); my $link_tag = Mojo::DOM->new_tag( 'link', - 'https://burguillos.info/' . $category->{slur} ); + 'https://burguillos.info/' . $category->{slug} ); $channel_tag->child_nodes->first->append_content($title_tag); $channel_tag->child_nodes->first->append_content($description_tag); $channel_tag->child_nodes->first->append_content($link_tag); @@ -94,9 +102,10 @@ sub _post_to_rss { my $guid = Mojo::DOM->new_tag( 'guid', $post->{slug} ); my $date = Mojo::DOM->new_tag( 'pubDate', - ''.DateTime::Format::Mail->format_datetime( + '' + . DateTime::Format::Mail->format_datetime( DateTime::Format::ISO8601->parse_datetime( $post->{date} ) - ) + ) ); $item_tag->child_nodes->first->append_content($title_tag); @@ -112,15 +121,17 @@ sub post { my $slug = $self->param('slug'); my ( $posts_categories, $posts_slug ) = BurguillosInfo::Posts->new->Retrieve; - my $categories = BurguillosInfo::Categories->new->Retrieve; - my $post = $posts_slug->{$slug}; + my $categories = BurguillosInfo::Categories->new->Retrieve; + my $post = $posts_slug->{$slug}; if ( !defined $post ) { $self->render( template => '404', status => 404 ); return; } my $current_category = $categories->{ $post->{category} }; - $self->stash(ogimage => 'https://burguillos.info/posts/'.$post->{slug}.'-preview.png'); - $self->stash(useragent => $self->req->headers->user_agent); + my $base_url = $self->config('base_url'); + $self->stash( + ogimage => $base_url . '/posts/' . $post->{slug} . '-preview.png' ); + $self->stash( useragent => $self->req->headers->user_agent ); $self->render( post => $post, current_category => $current_category ); } @@ -129,30 +140,48 @@ sub category { my $categories = BurguillosInfo::Categories->new->Retrieve; my $category_name = $self->param('category'); my $current_category = $categories->{$category_name}; + my $base_url = $self->config('base_url'); if ( !defined $current_category ) { $self->render( template => '404', status => 404 ); return; } $self->render( - template => 'page/index', - categories => $categories, + template => 'page/index', + categories => $categories, + ogimage => $base_url . '/' . $current_category->{slug} . '-preview.png', current_category => $current_category ); } +sub get_category_preview { + my $self = shift; + my $category_slug = $self->param('category'); + my $category_model = BurguillosInfo::Categories->new; + my $categories = $category_model->Retrieve; + if ( !defined $categories->{$category_slug} ) { + $self->render( template => '404', status => 404 ); + return; + } + my $category = $categories->{$category_slug}; + $self->render( + format => 'png', + data => $category_model->PreviewOg($category) + ); +} + sub get_post_preview { - my $self = shift; - my $slug = $self->param('slug'); - my $post_model = BurguillosInfo::Posts->new; - my ( $posts_categories, $posts_slug ) = $post_model->Retrieve; - if ( !defined $posts_slug->{$slug} ) { - $self->render( template => '404', status => 404 ); - return; - } - my $post = $posts_slug->{$slug}; - $self->render( - format => 'png', - data => $post_model->PostPreviewOg($post) - ); + my $self = shift; + my $slug = $self->param('slug'); + my $post_model = BurguillosInfo::Posts->new; + my ( $posts_categories, $posts_slug ) = $post_model->Retrieve; + if ( !defined $posts_slug->{$slug} ) { + $self->render( template => '404', status => 404 ); + return; + } + my $post = $posts_slug->{$slug}; + $self->render( + format => 'png', + data => $post_model->PreviewOg($post) + ); } 1; diff --git a/lib/BurguillosInfo/Controller/Robots.pm b/lib/BurguillosInfo/Controller/Robots.pm new file mode 100644 index 0000000..d572873 --- /dev/null +++ b/lib/BurguillosInfo/Controller/Robots.pm @@ -0,0 +1,14 @@ +package BurguillosInfo::Controller::Robots; +use Mojo::Base 'Mojolicious::Controller', '-signatures'; + +sub robots($self) { + my $robots_txt = <<"EOF"; +Sitemap: @{[$self->config('base_url')]}/sitemap.xml + +User-Agent: * +Disallow: /stats +Disallow: /stats/* +EOF + $self->render(text => $robots_txt, format => 'txt'); +} +1; diff --git a/lib/BurguillosInfo/Controller/Sitemap.pm b/lib/BurguillosInfo/Controller/Sitemap.pm new file mode 100644 index 0000000..9a364ac --- /dev/null +++ b/lib/BurguillosInfo/Controller/Sitemap.pm @@ -0,0 +1,130 @@ +package BurguillosInfo::Controller::Sitemap; + +use v5.34.1; + +use strict; +use warnings; + +use BurguillosInfo::Categories; +use BurguillosInfo::Posts; + +use DateTime::Format::ISO8601; + +use XML::Twig; + +use Mojo::Base 'Mojolicious::Controller', '-signatures'; + +sub sitemap ($self) { + my $categories = BurguillosInfo::Categories->new->Retrieve; + my $dom = Mojo::DOM->new_tag( + 'urlset', + xmlns => 'http://www.sitemaps.org/schemas/sitemap/0.9', + undef + ); + $dom->xml(1); + for my $category_key ( keys %$categories ) { + $self->_append_category_dom( $dom, $category_key, $categories ); + } + my $xml_string = "$dom"; + my $document = XML::Twig->new(pretty_print=> 'indented'); + $xml_string = $document->parse($xml_string)->sprint; + $self->render(text => $xml_string, format => 'xml'); +} + +sub _append_category_dom ( $self, $dom, $category_key, $categories ) { + my $category = $categories->{$category_key}; + my $slug = $category->{'slug'}; + my $date_publish_category; + my $date_last_modification_category; + + my ( $posts_categories, $posts_slug ) = + BurguillosInfo::Posts->new->Retrieve; + for my $post ( $posts_categories->{$category_key}->@* ) { + ( $date_publish_category, $date_last_modification_category ) = + _get_dates_for_category( $date_publish_category, + $date_last_modification_category, $post ); + my $url_post = $self->_generate_url_for_post($post); + $dom->child_nodes->first->append_content($url_post); + } + my $url = Mojo::DOM->new_tag('url'); + my $base_url = $self->config('base_url'); + my $location_tag = Mojo::DOM->new_tag( loc => "$base_url/$slug" ); + my $final_date_last_modification_category = + _compare_dates_return_most_recent( $date_publish_category, + $date_last_modification_category ); + if (defined $final_date_last_modification_category) { + my $last_modification_tag = + Mojo::DOM->new_tag( lastmod => $final_date_last_modification_category ); + $url->child_nodes->first->append_content($last_modification_tag); + } + $self->_append_attributes_category_sitemap($dom, $category_key, $categories); + my $priority_tag = Mojo::DOM->new_tag( priority => 0.6 ); + $url->child_nodes->first->append_content($location_tag); + $url->child_nodes->first->append_content($priority_tag); + + $dom->child_nodes->first->append_content($url); +} + +sub _append_attributes_category_sitemap($self, $dom, $category_key, $categories) { + my $base_url = $self->config('base_url'); + my $category = $categories->{$category_key}; + for my $attribute (keys $category->{attributes}->%*) { + my $url = Mojo::DOM->new_tag('url'); + my $location_tag = Mojo::DOM->new_tag( loc => "$base_url/$category_key/atributo/$attribute" ); + $url->child_nodes->first->append_content($location_tag); + $dom->child_nodes->first->append_content($url); + } +} + +sub _generate_url_for_post ( $self, $post ) { + my $url_tag = Mojo::DOM->new_tag('url'); + my $date = $post->{date}; + my $date_last_modification_post = $post->{last_modification_date}; + my $final_date_last_modification_post = + _compare_dates_return_most_recent( $date, $date_last_modification_post ); + my $base_url = $self->config('base_url'); + my $url_resource = "$base_url/posts/@{[$post->{slug}]}"; + my $last_modification_tag = + Mojo::DOM->new_tag( lastmod => $final_date_last_modification_post ); + my $location_tag = Mojo::DOM->new_tag( loc => $url_resource ); + $url_tag->child_nodes->first->append_content($location_tag); + $url_tag->child_nodes->first->append_content($last_modification_tag); + return $url_tag; +} + +my $error_no_dates = "Undefined dates"; + +sub _get_dates_for_category ( $current_date_publish, + $current_date_modification, $post ) +{ + my @return_list; + @return_list = ( + _compare_dates_return_most_recent( + $current_date_publish, $post->{date} + ), + _compare_dates_return_most_recent( + $current_date_publish, $post->{last_modification_date} + ), + ); + return @return_list; + +} + +sub _compare_dates_return_most_recent ( $date_a, $date_b ) { + if ( !defined $date_a && !defined $date_b ) { + return undef; + } + if ( !defined $date_a ) { + return $date_b; + } + if ( !defined $date_b ) { + return $date_a; + } + my $date_a_dt = DateTime::Format::ISO8601->parse_datetime($date_a); + my $date_b_dt = DateTime::Format::ISO8601->parse_datetime($date_b); + if ( $date_a_dt >= $date_b_dt ) { + return $date_a; + } + return $date_b; +} +1; diff --git a/lib/BurguillosInfo/DB/Migrations.pm b/lib/BurguillosInfo/DB/Migrations.pm index f648836..a860028 100644 --- a/lib/BurguillosInfo/DB/Migrations.pm +++ b/lib/BurguillosInfo/DB/Migrations.pm @@ -6,25 +6,31 @@ use strict; use warnings; sub MIGRATIONS { - return ( - 'CREATE TABLE options ( - name TEXT PRIMARY KEY, - value TEXT - )', - 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp"', - 'CREATE TABLE paths ( - path TEXT PRIMARY KEY, - first_seen timestamp DEFAULT NOW() - )', - 'CREATE TABLE requests ( - uuid UUID DEFAULT uuid_generate_v4(), - remote_address TEXT NOT NULL, - user_agent TEXT NOT NULL, - params JSON NOT NULL, - date timestamp DEFAULT NOW(), - path TEXT, - FOREIGN KEY (path) REFERENCES paths(path) - )', - ); + return ( + 'CREATE TABLE options ( + name TEXT PRIMARY KEY, + value TEXT + )', + 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp"', + 'CREATE TABLE paths ( + path TEXT PRIMARY KEY, + first_seen timestamp DEFAULT NOW() + )', + 'CREATE TABLE requests ( + uuid UUID DEFAULT uuid_generate_v4(), + remote_address TEXT NOT NULL, + user_agent TEXT NOT NULL, + params JSON NOT NULL, + date timestamp DEFAULT NOW(), + path TEXT, + FOREIGN KEY (path) REFERENCES paths(path) + )', + 'ALTER TABLE paths ADD column last_seen TIMESTAMP;', + 'ALTER TABLE paths ALTER COLUMN last_seen SET DEFAULT NOW();', + 'ALTER TABLE requests ADD PRIMARY KEY (uuid)', + 'CREATE INDEX request_extra_index on requests (date, path);', + 'ALTER TABLE requests ADD column referer text;', + 'CREATE INDEX request_referer_index on requests (referer);', + ); } 1; diff --git a/lib/BurguillosInfo/Posts.pm b/lib/BurguillosInfo/Posts.pm index f2e71d9..d5551ca 100644 --- a/lib/BurguillosInfo/Posts.pm +++ b/lib/BurguillosInfo/Posts.pm @@ -5,26 +5,25 @@ use v5.34.1; use strict; use warnings; +use feature 'signatures'; + use Data::Dumper; use MIME::Base64; +use BurguillosInfo::Categories; + use Const::Fast; use Mojo::DOM; use Path::Tiny; use DateTime::Format::ISO8601; use DateTime; -use SVG; -use Capture::Tiny qw/capture/; + +use BurguillosInfo::Preview; const my $CURRENT_FILE => __FILE__; const my $ROOT_PROJECT => path($CURRENT_FILE)->parent->parent->parent; const my $PUBLIC_DIR => $ROOT_PROJECT->child('public'); const my $POSTS_DIR => $ROOT_PROJECT->child('content/posts'); -const my $BURGUILLOS_LOGO => $PUBLIC_DIR->child('img/burguillos.png'); -const my $SVG_WIDTH => 1200; -const my $SVG_HEIGHT => 627; -const my $SVG_EMBEDDED_IMAGE_MAX_WIDTH => 1000; -const my $SVG_EMBEDDED_IMAGE_MAX_HEIGHT => 200; my $cached_posts_by_category; my $cached_posts_by_slug; @@ -41,7 +40,13 @@ sub _ReturnCacheFilter { my $current_date = DateTime->now; for my $category ( keys %$cached_posts_by_category ) { for my $post ( @{ $cached_posts_by_category->{$category} } ) { - my $date_post = $iso8601->parse_datetime( $post->{date} ); + my $date_post; + eval { + $date_post = $iso8601->parse_datetime( $post->{date} ); + }; + if ($@) { + print Data::Dumper::Dumper $post; + } if ( $date_post > $current_date ) { next; } @@ -53,204 +58,139 @@ sub _ReturnCacheFilter { return ( \%posts_by_category_filtered, \%posts_by_slug_filtered ); } +sub _GeneratePostFromFile ( $self, $post_file ) { + warn "Bad file $post_file, omiting...", return + if !-f $post_file || $post_file !~ /\.xml$/; + my $dom = Mojo::DOM->new( $post_file->slurp_utf8 ); + my $title = $dom->at(':root > title')->text + or die "Missing title at $post_file."; + my $author = $dom->at(':root > author')->text + or die "Missing author at $post_file."; + my $date = $dom->at(':root > date')->text + or die "Missing date at $post_file."; + my $ogdesc = $dom->at(':root > ogdesc')->text + or die "Missing ogdesc at $post_file"; + my $category = $dom->at(':root > category')->text + or die "Missing category at $post_file."; + my $slug = $dom->at(':root > slug')->text + or die "Missing slug at $post_file."; + my $content = $dom->at(':root > content')->content + or die "Missing content at $post_file."; + my $image_element = $dom->at(':root > img'); + my $image; + my $attributes = $self->_GetAttributes($post_file, $dom); + + if ( defined $image_element ) { + $image = $image_element->attr->{src}; + } + + my $last_modification_date_element = + $dom->at(':root > last_modification_date'); + my $last_modification_date; + if ( defined $last_modification_date_element ) { + $last_modification_date = $last_modification_date_element->content; + } + + return { + title => $title, + author => $author, + date => $date, + ogdesc => $ogdesc, + category => $category, + slug => $slug, + content => $content, + ( + ( defined $last_modification_date ) + ? ( last_modification_date => $last_modification_date ) + : () + ), + ( ( defined $image ) ? ( image => $image ) : () ), + attributes => $attributes, + }; +} + +sub _GetAttributes($self, $post_file, $dom) { + my $attributes_tag = $dom->at(':root > attributes'); + my %attributes; + if (defined $attributes_tag) { + my @attribute_list = $attributes_tag->find('attributes > attribute')->map('text')->each; + %attributes = map { + my $identifier = $_; + ($identifier => 1); + } @attribute_list; + } + return \%attributes; + +} + +sub _GeneratePostCache ($self) { + $cached_posts_by_category = {}; + $cached_posts_by_slug = {}; + for my $post_file ( sort { $b cmp $a } $POSTS_DIR->children ) { + my $post = $self->_GeneratePostFromFile($post_file); + if (!defined $post) { + next; + } + my $category = $post->{category}; + $cached_posts_by_category->{$category} //= []; + my $slug = $post->{slug}; + my $category_posts = $cached_posts_by_category->{$category}; + $cached_posts_by_slug->{$slug} = $post; + push @$category_posts, $post; + } +} + sub Retrieve { my $self = shift; if ( defined $cached_posts_by_category && defined $cached_posts_by_slug ) { return $self->_ReturnCacheFilter; } - $cached_posts_by_category = {}; - $cached_posts_by_slug = {}; - for my $post_file ( sort { $b cmp $a } $POSTS_DIR->children ) { - warn "Bad file $post_file, omiting...", next - if !-f $post_file || $post_file !~ /\.xml$/; - my $dom = Mojo::DOM->new( $post_file->slurp_utf8 ); - my $title = $dom->at(':root > title')->text - or die "Missing title at $post_file."; - my $author = $dom->at(':root > author')->text - or die "Missing author at $post_file."; - my $date = $dom->at(':root > date')->text - or die "Missing date at $post_file."; - my $ogdesc = $dom->at(':root > ogdesc')->text - or die "Missing ogdesc at $post_file"; - my $category = $dom->at(':root > category')->text - or die "Missing category at $post_file."; - my $slug = $dom->at(':root > slug')->text - or die "Missing slug at $post_file."; - my $content = $dom->at(':root > content')->content - or die "Missing content at $post_file."; - my $image_element = $dom->at(':root > img'); - my $image; - - if ( defined $image_element ) { - $image = $image_element->attr->{src}; - } - - my $post = { - title => $title, - author => $author, - date => $date, - ogdesc => $ogdesc, - category => $category, - slug => $slug, - content => $content, - ( ( defined $image ) ? ( image => $image ) : () ), - }; - $cached_posts_by_category->{$category} //= []; - my $category_posts = $cached_posts_by_category->{$category}; - $cached_posts_by_slug->{$slug} = $post; - push @$category_posts, $post; - } + $self->_GeneratePostCache(); return $self->_ReturnCacheFilter; } -sub PostPreviewOg { +my $cache_all_post_categories = {}; +sub RetrieveAllPostsForCategory ( $self, $category_name ) { + if (defined $cache_all_post_categories->{$category_name}) { + return $cache_all_post_categories->{$category_name}; + } + my $categories = BurguillosInfo::Categories->new->Retrieve; + my $category = $categories->{$category_name}; + my $posts = $self->RetrieveDirectPostsForCategory($category_name); + for my $child_category ( $category->{children}->@* ) { + my $child_category_name = $child_category->{slug}; + push @$posts, + @{$self->RetrieveDirectPostsForCategory($child_category_name)}; + } + @$posts = sort { + DateTime::Format::ISO8601->parse_datetime($b->{date}) <=> + DateTime::Format::ISO8601->parse_datetime($a->{date}) + } @$posts; + $cache_all_post_categories->{$category_name} = $posts; + return $posts; +} + +sub RetrieveDirectPostsForCategory ( $self, $category_name ) { + my ($post_by_category) = $self->Retrieve; + my $categories = BurguillosInfo::Categories->new->Retrieve; + my $category = $categories->{$category_name}; + if ( !defined $category ) { + die "$category_name category does not exists"; + } + my $posts = $post_by_category->{$category_name}; + $posts //= []; + return [@$posts]; +} + +sub PreviewOg { my $self = shift; my $post = shift; my $title = $post->{title}; my $content = $post->{content}; - my $dom = Mojo::DOM->new($content); - $content = $dom->all_text; - - my @content_divided_in_lines = split /\n/, $content; - my @new_content; - my $n_chars_per_line = 70; - - for my $line (@content_divided_in_lines) { - if ( length($line) <= $n_chars_per_line ) { - push @new_content, $line; - next; - } - my $last_word = ''; - while ( $line =~ /(.{1,${n_chars_per_line}})/g ) { - my $new_line = $last_word . $1; - $new_line =~ s/(\S*)$//; - $last_word = $1; - push @new_content, $new_line; - } - if ($last_word) { - $new_content[$#new_content] .= $last_word; - } - } - - my $svg = - $self->_GenerateSVGPostPreview( $title, \@new_content, $post->{image} ); - my ( $stdout, $stderr ) = capture { - open my $fh, '|-', qw{convert /dev/stdin png:fd:1}; - binmode $fh, 'utf8'; - print $fh $svg; - close $fh; - }; - say STDERR $stderr; - return $stdout; + my $image_file = $post->{image}; + return BurguillosInfo::Preview->Generate($title, $content, $image_file); } -sub _AttachImageSVG { - my $self = shift; - my $svg = shift; - my $image = shift; - $image = $PUBLIC_DIR->child( './' . $image ); - my ( $stdout, $stderr, $error ) = capture { - system qw/identify -format "%wx%h"/, $image; - }; - if ($error) { - warn "$image not recognized by identify."; - return; - } - my ( $width, $height ) = $stdout =~ /^"(\d+)x(\d+)"$/; - if ( $height > $SVG_EMBEDDED_IMAGE_MAX_HEIGHT ) { - $width /= $height / $SVG_EMBEDDED_IMAGE_MAX_HEIGHT; - $width = int($width); - $height = $SVG_EMBEDDED_IMAGE_MAX_HEIGHT; - } - if ( $width > $SVG_EMBEDDED_IMAGE_MAX_WIDTH ) { - $height /= $width / $SVG_EMBEDDED_IMAGE_MAX_WIDTH; - $height = int($height); - $width = $SVG_EMBEDDED_IMAGE_MAX_WIDTH; - } - - my $x = int( ( $SVG_WIDTH / 2 ) - ( $width / 2 ) ); - my $y = 90; - my ($output) = capture { - system qw/file --mime-type/, $image; - }; - my ($format) = $output =~ /(\S+)$/; - $svg->image( - x => $x, - y => $y, - width => $width, - height => $height, - -href => "data:$format;base64," . encode_base64( $image->slurp ) - ); - return $y + $height + 50; -} - -sub _GenerateSVGPostPreview { - my $self = shift; - my $title = shift; - my $content = shift; - my $image = shift; - my @content = @$content; - my $svg = SVG->new( width => $SVG_WIDTH, height => $SVG_HEIGHT ); - $svg->rect( - x => 0, - y => 0, - width => 1200, - height => 50, - style => { fill => 'blueviolet' } - ); - $svg->rect( - x => 0, - y => 50, - width => 1200, - height => 627, - style => { fill => '#F8F8FF' } - ); - - my $group = $svg->group( - id => 'group', - style => { - font => 'Arial', - 'font-size' => 30, - } - ); - - $group->image( - x => 10, - y => 5, - width => 40, - height => 40, - -href => 'data:image/png;base64,' - . encode_base64( $BURGUILLOS_LOGO->slurp ) - ); - $group->text( - x => 60, - y => 40, - style => { 'font-size' => 50, fill => '#f2eb8c' } - )->cdata('Burguillos.info'); - my $new_y; - - if ( defined $image ) { - $new_y = $self->_AttachImageSVG( $group, $image ); - } - $new_y //= 100; - $group->text( - x => 10, - y => $new_y, - style => { 'font-size' => 50 } - )->cdata($title); - - my $n = 0; - for my $line (@content) { - $group->text( - x => 10, - y => $new_y + 40 + ( 30 * $n ), - style => { 'font-size' => 38 } - )->cdata($line); - $n++; - } - path($ROOT_PROJECT)->child('a.svg')->spew_utf8( $svg->xmlify ); - return $svg->xmlify; -} 1; diff --git a/lib/BurguillosInfo/Preview.pm b/lib/BurguillosInfo/Preview.pm new file mode 100644 index 0000000..4fcf274 --- /dev/null +++ b/lib/BurguillosInfo/Preview.pm @@ -0,0 +1,195 @@ +package BurguillosInfo::Preview; + +use v5.36.0; + +use strict; +use warnings; + +use feature 'signatures'; + +use SVG; +use Path::Tiny; + +use Const::Fast; +use Capture::Tiny qw/capture/; +use MIME::Base64; + +const my $CURRENT_FILE => __FILE__; +const my $ROOT_PROJECT => path($CURRENT_FILE)->parent->parent->parent; +const my $PUBLIC_DIR => $ROOT_PROJECT->child('public'); +const my $BURGUILLOS_LOGO => $PUBLIC_DIR->child('img/burguillos.webp'); +const my $SVG_WIDTH => 1200; +const my $SVG_HEIGHT => 627; +const my $SVG_EMBEDDED_IMAGE_MAX_WIDTH => 1000; +const my $SVG_EMBEDDED_IMAGE_MAX_HEIGHT => 200; + +sub Generate($self, $title, $content, $image_file) { + my $dom = Mojo::DOM->new($content); + $content = $dom->all_text; + + + my $svg = + $self->_GenerateSVGPreview( $title, $self->_DivideTextContentInLines($content), $image_file ); + return $self->_SVGToPNG($svg); +} + +sub _ToPng($self, $image) { + if ($image =~ /\.\w+$/) { + my $new_image = $image =~ s/\.\w+$/.generated.png/r; + say $new_image; + if (!-e $new_image) { + system 'convert', "$image", "$new_image"; + } + $image = $new_image; + } + return path($image); +} + +sub _GenerateSVGPreviewHeaderBar($self, $svg, $group) { + $group->rect( + x => 0, + y => 0, + width => 1200, + height => 50, + style => { fill => 'blueviolet' } + ); + $group->rect( + x => 0, + y => 50, + width => 1200, + height => 627, + style => { fill => '#F8F8FF' } + ); + + + my $burguillos_logo_png = path($self->_ToPng($BURGUILLOS_LOGO)); + say $burguillos_logo_png; + say ''.$burguillos_logo_png; + $group->image( + x => 10, + y => 5, + width => 40, + height => 40, + -href => 'data:image/png;base64,' + . encode_base64( $burguillos_logo_png->slurp ) + ); + $group->text( + x => 60, + y => 40, + style => { 'font-size' => 50, fill => '#f2eb8c' } + )->cdata('Burguillos.info'); +} + +sub _GenerateSVGPreview($self, $title, $content, $image_file) { + my @content = @$content; + my $svg = SVG->new( width => $SVG_WIDTH, height => $SVG_HEIGHT ); + + my $group = $svg->group( + id => 'group', + style => { + font => 'Arial', + 'font-size' => 30, + } + ); + + $self->_GenerateSVGPreviewHeaderBar($svg, $group); + + my $new_y; + + if ( defined $image_file ) { + $new_y = $self->_AttachImageSVG( $group, $image_file ); + } + + $new_y //= 100; + $group->text( + x => 10, + y => $new_y, + style => { 'font-size' => 50 } + )->cdata($title); + + my $n = 0; + for my $line (@content) { + $group->text( + x => 10, + y => $new_y + 40 + ( 30 * $n ), + style => { 'font-size' => 38 } + )->cdata($line); + $n++; + } + return $svg->xmlify; +} + +sub _SVGToPNG($self, $svg) { + my ( $stdout, $stderr ) = capture { + open my $fh, '|-', qw{convert /dev/stdin png:fd:1}; + binmode $fh, 'utf8'; + print $fh $svg; + close $fh; + }; + say STDERR $stderr; + return $stdout; +} + +sub _DivideTextContentInLines($self, $content) { + my @content_divided_in_lines = split /\n/, $content; + my @new_content; + my $n_chars_per_line = 70; + + for my $line (@content_divided_in_lines) { + if ( length($line) <= $n_chars_per_line ) { + push @new_content, $line; + next; + } + my $last_word = ''; + while ( $line =~ /(.{1,${n_chars_per_line}})/g ) { + my $new_line = $last_word . $1; + $new_line =~ s/(\S*)$//; + $last_word = $1; + push @new_content, $new_line; + } + if ($last_word) { + $new_content[$#new_content] .= $last_word; + } + } + return \@new_content; +} +sub _AttachImageSVG($self, $svg, $image_file) { + $image_file = $PUBLIC_DIR->child( './' . $image_file ); + $image_file = path($self->_ToPng($image_file)); + my ( $stdout, $stderr, $error ) = capture { + system qw/identify -format "%wx%h"/, $image_file; + }; + if ($error) { + warn "$image_file not recognized by identify."; + return; + } + my ( $width, $height ) = $stdout =~ /^"(\d+)x(\d+)"$/; + if ( $height > $SVG_EMBEDDED_IMAGE_MAX_HEIGHT ) { + $width /= $height / $SVG_EMBEDDED_IMAGE_MAX_HEIGHT; + $width = int($width); + $height = $SVG_EMBEDDED_IMAGE_MAX_HEIGHT; + } + + if ( $width > $SVG_EMBEDDED_IMAGE_MAX_WIDTH ) { + $height /= $width / $SVG_EMBEDDED_IMAGE_MAX_WIDTH; + $height = int($height); + $width = $SVG_EMBEDDED_IMAGE_MAX_WIDTH; + } + + my $x = int( ( $SVG_WIDTH / 2 ) - ( $width / 2 ) ); + my $y = 90; + my ($output) = capture { + system qw/file --mime-type/, $image_file; + }; + my ($format) = $output =~ /(\S+)$/; + $svg->image( + x => $x, + y => $y, + width => $width, + height => $height, + -href => "data:$format;base64," . encode_base64( $image_file->slurp ) + ); + return $y + $height + 50; +} + +1; diff --git a/lib/BurguillosInfo/Tracking.pm b/lib/BurguillosInfo/Tracking.pm index 1a8c9d9..088c256 100644 --- a/lib/BurguillosInfo/Tracking.pm +++ b/lib/BurguillosInfo/Tracking.pm @@ -5,6 +5,8 @@ use v5.34.1; use strict; use warnings; +use feature 'signatures'; + use JSON; use Const::Fast; @@ -17,7 +19,6 @@ SELECT COUNT(DISTINCT (remote_address, user_agent)) FROM requests EOF - sub new { my $class = shift; $app = shift; @@ -25,81 +26,165 @@ sub new { return bless {}, $class; } +sub _add_path ( $self, $url ) { + my $dbh = BurguillosInfo::DB->connect($app); + $dbh->do( <<'EOF', undef, $url ); +INSERT INTO paths (path) VALUES($1) +ON CONFLICT (path) DO + UPDATE SET last_seen = NOW() where paths.path = $1; +EOF +} + +sub _update_null_last_seen_paths_if_any ($self) { + my $dbh = BurguillosInfo::DB->connect($app); + $dbh->do( <<'EOF', undef ); + +UPDATE paths +SET last_seen = requests_for_path.last_date +FROM ( + SELECT requests.path, max(requests.date) as last_date + FROM requests + GROUP BY requests.path +) requests_for_path +WHERE paths.last_seen IS NULL AND requests_for_path.path = paths.path; +EOF +} + +sub _register_request_query ( $self, $remote_address, $user_agent, + $params_json, $path, $referer ) +{ + my $dbh = BurguillosInfo::DB->connect($app); + $dbh->do( + <<'EOF', undef, $remote_address, $user_agent, $params_json, $path, $referer ); +INSERT INTO requests(remote_address, user_agent, params, path, referer) + VALUES (?, ?, ?, ?, ?); +EOF +} + sub register_request { my $self = shift; my $c = shift; my $path = $c->req->url->path; - my $dbh = BurguillosInfo::DB->connect($app); - $dbh->do( <<'EOF', undef, $c->req->url->path ); -INSERT INTO paths (path) VALUES (?) ON CONFLICT DO NOTHING; -EOF + my $dbh = BurguillosInfo::DB->connect($app); + $self->_add_path($path); + $self->_update_null_last_seen_paths_if_any(); my $remote_address = $c->tx->remote_address; my $user_agent = $c->req->headers->user_agent; + my $referer = $c->req->headers->referer // ''; my $params_json = encode_json( $c->req->params->to_hash ); - $dbh->do( - <<'EOF', undef, $remote_address, $user_agent, $params_json, $path ); -INSERT INTO requests(remote_address, user_agent, params, path) - VALUES (?, ?, ?, ?); -EOF - say "Registered $remote_address with user agent $user_agent visited $path with $params_json"; + $self->_register_request_query( $remote_address, $user_agent, $params_json, + $path, $referer ); + say +"Registered $remote_address with user agent $user_agent visited $path with $params_json"; } - sub get_global_data { - my $self = shift; - my $c = shift; - my $app = $c->app; - my $dbh = BurguillosInfo::DB->connect($app); - my $data = $dbh->selectrow_hashref(<<"EOF", undef); +sub get_global_data { + my $self = shift; + my $c = shift; + my $app = $c->app; + my $dbh = BurguillosInfo::DB->connect($app); + my $data = $dbh->selectrow_hashref( <<"EOF", undef ); SELECT - ( - $SELECT_GLOBAL - ) as unique_ips, - ( - $SELECT_GLOBAL - where date > NOW() - interval '1 day' - ) as unique_ips_last_24_hours, - ( - $SELECT_GLOBAL - where date > NOW() - interval '1 week' - ) as unique_ips_last_week, - ( - $SELECT_GLOBAL - where date > NOW() - interval '1 month' - ) as unique_ips_last_month; - - + ( + $SELECT_GLOBAL + where date > NOW() - interval '1 day' + ) as unique_ips_last_24_hours, + ( + $SELECT_GLOBAL + where date > NOW() - interval '1 week' + ) as unique_ips_last_week, + ( + $SELECT_GLOBAL + where date > NOW() - interval '1 month' + ) as unique_ips_last_month; EOF - return $data; - } + return $data; +} - sub get_data_for_urls { - my $self = shift; - my $c = shift; - my $app = $c->app; - my $dbh = BurguillosInfo::DB->connect($app); - my $data = $dbh->selectall_arrayref(<<"EOF", {Slice => {}}); +my $GOOGLE_REFERER_REGEX = "'^https?://(?:www\\.)?google\\.\\w'"; +my $GOOGLE_SELECT = "$SELECT_GLOBAL +where requests.path = paths.path + and requests.referer IS NOT NULL + and requests.referer ~* $GOOGLE_REFERER_REGEX + and date > NOW()"; + +sub get_google_data { + my $self = shift; + my $c = shift; + my $app = $c->app; + my $dbh = BurguillosInfo::DB->connect($app); + my $data = $dbh->selectall_arrayref(<<"EOF", { Slice => {} } ); + SELECT paths.path, + ( + $GOOGLE_SELECT - interval '1 hour' + ) as unique_ips_last_1_hour, + ( + $GOOGLE_SELECT - interval '3 hour' + ) as unique_ips_last_3_hours, + ( + $GOOGLE_SELECT - interval '6 hour' + ) as unique_ips_last_6_hours, + ( + $GOOGLE_SELECT - interval '12 hour' + ) as unique_ips_last_12_hours, + ( + $GOOGLE_SELECT - interval '1 day' + ) as unique_ips_last_24_hours, + ( + $GOOGLE_SELECT - interval '1 week' + ) as unique_ips_last_week, + ( + $GOOGLE_SELECT - interval '1 month' + ) as unique_ips_last_month +FROM paths right join requests on paths.path = requests.path +WHERE paths.last_seen > NOW() - INTERVAL '1 month' + and requests.referer ~* $GOOGLE_REFERER_REGEX + and requests.date > NOW() - INTERVAL '1 month' +GROUP BY + paths.path; +EOF + return $data; +} + +sub get_data_for_urls { + my $self = shift; + my $c = shift; + my $app = $c->app; + my $dbh = BurguillosInfo::DB->connect($app); + my $data = $dbh->selectall_arrayref( <<"EOF", { Slice => {} } ); SELECT paths.path, - ( - $SELECT_GLOBAL - where requests.path = paths.path - ) as unique_ips, - ( - $SELECT_GLOBAL - where requests.path = paths.path and date > NOW() - interval '1 day' - ) as unique_ips_last_24_hours, - ( - $SELECT_GLOBAL - where requests.path = paths.path and date > NOW() - interval '1 week' - ) as unique_ips_last_week, - ( - $SELECT_GLOBAL - where requests.path = paths.path and date > NOW() - interval '1 month' - ) as unique_ips_last_month -FROM paths; - - + ( + $SELECT_GLOBAL + where requests.path = paths.path and date > NOW() - interval '1 hour' + ) as unique_ips_last_1_hour, + ( + $SELECT_GLOBAL + where requests.path = paths.path and date > NOW() - interval '3 hour' + ) as unique_ips_last_3_hours, + ( + $SELECT_GLOBAL + where requests.path = paths.path and date > NOW() - interval '6 hour' + ) as unique_ips_last_6_hours, + ( + $SELECT_GLOBAL + where requests.path = paths.path and date > NOW() - interval '12 hour' + ) as unique_ips_last_12_hours, + ( + $SELECT_GLOBAL + where requests.path = paths.path and date > NOW() - interval '1 day' + ) as unique_ips_last_24_hours, + ( + $SELECT_GLOBAL + where requests.path = paths.path and date > NOW() - interval '1 week' + ) as unique_ips_last_week, + ( + $SELECT_GLOBAL + where requests.path = paths.path and date > NOW() - interval '1 month' + ) as unique_ips_last_month +FROM paths +WHERE paths.last_seen > NOW() - INTERVAL '1 month'; EOF - return $data; + return $data; } 1; diff --git a/package.json b/package.json new file mode 100644 index 0000000..03b81f2 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "BurguillosInfo", + "version": "0.1.1", + "description": "", + "private": true, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "AGPL-v3", + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", + "eslint": "^8.40.0", + "eslint-plugin-no-relative-import-paths": "^1.5.2", + "typescript": "^5.0.4", + "webpack-cli": "^5.0.2" + }, + "dependencies": { + "tablesort": "^5.3.0" + } +} diff --git a/public/css/styles.css b/public/css/styles.css new file mode 100644 index 0000000..5cb0c37 --- /dev/null +++ b/public/css/styles.css @@ -0,0 +1,242 @@ +html { + height: 100%; } + +body { + margin: 0; + padding: 0; + overflow: hidden; + min-height: 100%; + width: 100%; + height: 100%; } + body p, body h1, body h2, body h3, body h4, body a { + font-family: 'arial'; } + body div.site-wrapper { + display: table; + width: 100%; + height: 100%; + /* For at least Firefox */ + min-height: 100%; + color: #2f4f4f; + background: url(../img/parque_patos.webp); + filter: blur(10px); + background-size: cover; + overflow: hidden; } + body div.page-contents { + position: absolute; + position: fixed; + overflow-y: scroll; + z-index: 2; + background: #FEFEFA; + color: #666362; + top: 0%; + left: 0%; + height: 100%; + width: 100%; } + body div.page-contents div.child-categories-mobile a { + padding-left: 2.5rem; } + body div.page-contents img { + max-width: 100%; + margin-left: auto; + margin-right: auto; + display: block; } + body div.page-contents table { + color: blueviolet; + background: #f2eb8c; + border: 3px solid blueviolet; + border-collapse: collapse; + width: 100%; + table-layout: fixed; } + body div.page-contents table td, body div.page-contents table th { + font-size: 12px; } + body div.page-contents th, body div.page-contents td { + border: 3px solid blueviolet; + border-collapse: collapse; + padding-right: 10px; + margin: 0; } + body div.page-contents div.description { + margin-top: 60px; + word-wrap: break-word; + padding: 1%; + margin-left: 3%; + margin-right: 3%; + margin-bottom: 1%; } + body div.page-contents div.description input { + display: block; } + body div.page-contents div.description div.suscribirse-rss img { + max-height: 300px; } + body div.page-contents div.description div.articles { + display: flex; + flex-direction: row; + flex-wrap: wrap; } + body div.page-contents div.description div.articles div.image-container { + margin-left: 2.5%; + margin-top: 10px; + height: 95%; + width: 95%; + display: flex; + min-height: 130px; + justify-content: center; + align-items: center; } + body div.page-contents div.description div.articles div.image-container img { + max-height: 100%; + max-width: 100%; + min-width: 277px; + border: solid 1px black; } + body div.page-contents div.description div.articles a { + min-height: 90%; + width: 100%; + display: block; + text-decoration: none; + text-overflow: ellipsis; + margin-bottom: 30px; } + body div.page-contents div.description div.articles a article { + word-wrap: break-word; + width: 90%; + height: 90%; + padding: 5%; + padding-top: 1%; + background: #f2eb8c; + color: blueviolet; + box-shadow: 8px 8px 1px 0px #8ddfd6; + border: 3px solid black; } + body div.page-contents div.description div.articles a article p, body div.page-contents div.description div.articles a article h4, body div.page-contents div.description div.articles a article h3, body div.page-contents div.description div.articles a article h2 { + margin: 0px; } + body div.page-contents div.description div.articles a article p { + font-size: 0.9rem; } + body div.page-contents div.description div.articles a article div.article-up-part { + height: 12em; } + body div.page-contents div.description div.articles a article div.article-down-part { + margin-top: 2em; + height: 9em; + display: flex; + align-items: end; + padding-bottom: 2em; } + body div.page-contents div.description div.articles a article:hover { + background: blueviolet; + color: #f2eb8c; } + body div.page-contents div.description div.articles a article p.date { + text-align: right; } + body div.page-contents div.description div.articles a article p.author { + text-align: right; } + body div.page-contents div.description a.suscribe-category-rss { + background: blueviolet; + width: 40px; + height: 40px; + padding: 10px; + border-radius: 5px; + display: inline-block; } + body div.page-contents div.description a.suscribe-category-rss img { + width: 40px; + height: 40px; } + body div.page-contents nav > a.menu-expand > img { + width: 30px; + height: 30px; + padding-top: 15px; } + body div.page-contents nav > a > img.index-image-menu { + vertical-align: middle; + width: 50px; + height: 50px; + padding-bottom: 10px; } + body div.page-contents nav.desktop { + display: none; } + body div.page-contents nav.desktop a { + vertical-align: middle; + background: blueviolet; } + body div.page-contents nav { + overflow: auto; + display: block; + font-size: 25px; + margin: 0px; } + body div.page-contents nav a.go-to-index img { + margin-top: 5%; } + body div.page-contents nav a { + padding-left: 10px; + padding-right: 10px; + height: 100%; + text-decoration: none; + color: #f2eb8c; + margin: 0; } + body div.page-contents nav a:hover { + background: #f2eb8c; + color: blueviolet; } + body div.page-contents nav a.selected { + background: #f2eb8c; + color: blueviolet; } + body div.page-contents nav a.menu-expand { + padding-bottom: 9px; } + body div.page-contents nav a.menu-expand .open-menu-icon-hover { + display: none; } + body div.page-contents nav a.menu-expand:hover .open-menu-icon-hover { + display: block; } + body div.page-contents nav a.menu-expand:hover .open-menu-icon { + display: none; } + body div.page-contents nav.mobile-shortcuts { + position: fixed; + display: flex; + width: 100%; + background: blueviolet; + height: 60px; } + body div.page-contents nav.mobile-shortcuts a { + height: 100%; + width: 16.66667%; } + body div.page-contents nav.mobile-shortcuts div { + width: 66.66667%; } + body div.page-contents nav.mobile-foldable { + display: none; + background: blueviolet; + color: #f2eb8c; } + body div.page-contents nav.mobile-foldable a { + display: block; } + body div.page-contents nav.mobile-foldable.show { + display: block; } + body div.page-contents h1 { + text-align: center; } + body div.page-contents div.footer p, body div.page-contents div.footer h1, body div.page-contents div.footer h2, body div.page-contents div.footer h3, body div.page-contents div.footer h4, body div.page-contents div.footer a { + font-size: initial; } + body div.page-contents div.footer a.suscribe-category-rss { + padding: 7px; } + body div.page-contents div.footer a.suscribe-category-rss, body div.page-contents div.footer a.suscribe-category-rss > img { + width: 20px; + height: 20px; } + +@media (min-width: 450px) { + body div.page-contents table th, body div.page-contents table td { + font-size: 20px; } } + +@media (min-width: 694px) { + body div.page-contents div.description div.articles a { + width: 45%; + margin-left: 5%; } + body div.page-contents div.description div.articles a:nth-child(2n+1) { + margin-left: 0%; } } + +@media (min-width: 1100px) { + body div.page-contents { + top: 0%; + left: 5%; + height: 100%; + width: 90%; } + body div.page-contents nav.mobile-foldable, body div.page-contents nav.mobile-foldable.show { + display: none; } + body div.page-contents div.description { + margin-left: 10%; + margin-right: 10%; } + body div.page-contents nav.desktop { + display: block; + height: auto; } + body div.page-contents nav.desktop a { + display: table-cell; } + body div.page-contents nav.desktop a img.index-image-menu { + padding-top: 15px; } + body div.page-contents nav.mobile-shortcuts { + display: none; } } + +@media (min-width: 1333px) { + body div.page-contents div.description div.articles a { + width: 30%; + margin-left: 3%; } + body div.page-contents div.description div.articles a:nth-child(2n+1) { + margin-left: 3%; } + body div.page-contents div.description div.articles a:nth-child(3n+1) { + margin-left: 0%; } } + diff --git a/public/css/styles.scss b/public/css/styles.scss index 30933b0..21864ff 100644 --- a/public/css/styles.scss +++ b/public/css/styles.scss @@ -1,4 +1,4 @@ -$background: url(../img/parque_patos.jpg); +$background: url(../img/parque_patos.webp); $background-page: #FEFEFA; $color: #2f4f4f; $color-page: #666362; @@ -10,297 +10,400 @@ $accent-secondary: #fde68f; $primary-secondary: #590e11; html { - height: 100%; + height: 100%; } body { - p,h1,h2,h3,h4,a { - font-family: 'arial'; - } - margin: 0; - padding: 0; - overflow: hidden; - min-height: 100%; - width: 100%; - height: 100%; - div.site-wrapper { - display: table; - width: 100%; - height: 100%; /* For at least Firefox */ - min-height: 100%; - color: $color; - background: $background; - filter: blur(10px); - background-size: cover; - overflow: hidden; - } - div.page-contents { - position: absolute; - position: fixed; - overflow-y: scroll; - z-index: 2; - background: $background-page; - color: $color-page; - top: 0%; - left: 0%; - height: 100%; - width: 100%; - img { - max-width: 100%; - margin-left: auto; - margin-right: auto; - display: block; - } - table { - color: $background_div; - background: $color_div; - border: 3px solid $background_div; - border-collapse: collapse; - } - th,td { - border: 3px solid $background_div; - border-collapse: collapse; - padding-right: 10px; - margin: 0; - } - th,td { - font-size: 15px; - } - b,p,li { - font-size: 40px; - } - h3 { - font-size: 47px; - } - h2 { - font-size: 53px; - } - h1 { - font-size: 60px; - } - div.description { - input { - display: block; - } - word-wrap: break-word; - div.suscribirse-rss { - img { - max-height: 300px; - } - } - padding: 1%; - margin-left: 3%; - margin-right: 3%; - margin-bottom: 1%; - margin-top: 10%; - div.articles { - display: flex; - flex-direction: row; - flex-wrap: wrap; - a { - width: 100%; - display:block; - text-decoration: none; - text-overflow: ellipsis; - margin-bottom: 10px; - article { - word-wrap: break-word; - width: 90%; - p,h4,h3,h2 { - margin: 0px; - } - b,p { - font-size: 38px; - } - h4 { - font-size: 44px; - } - h3 { - font-size: 47px; - } - h2 { - font-size: 53px; - } - h1 { - font-size: 60px; - } - padding: 5%;; - padding-top: 1%; - background: $color_div; - color: $background_div; - box-shadow: 8px 8px 1px 0px #8ddfd6; - border: 3px solid black; - &:hover { - background: $background_div; - color: $color_div; - } - p.date { - font-size: 20px; - text-align: right; - } - p.author { - font-size: 30px; - text-align: right; - } - } - } - } - a.suscribe-category-rss { - background: $background_div; - width: 40px; - height: 40px; - padding: 10px; - border-radius: 5px; - display: inline-block; - img { - width: 40px; - height: 40px; - } - } - } - nav > a > img.open-menu-icon { - width: 30px; - height: 30px; - padding-top: 15px; - } - nav > a > img.index-image-menu { - vertical-align: middle; - width: 50px; - height: 50px; - padding-bottom: 10px; - } - nav.desktop { - display: none; - a { - vertical-align: middle; - background: $background_div; - } - } - nav { - overflow: auto; - display: block; - font-size: 35px; - margin: 0px; - a.go-to-index img { - margin-top: 5%; - } - a { - padding-left: 10px; - padding-right: 10px; - height: 100%; - text-decoration: none; - color: $color_div; - margin: 0; - &:hover { - background: $color_div; - color: $background_div; - } - &.selected { - background: $color_div; - color: $background_div; - } - } - a.menu-expand { - padding-bottom: 9px; - } - } + p, h1, h2, h3, h4, a { + font-family: 'arial'; + } - nav.mobile-shortcuts { - position: fixed; - display: flex; - width: 100%; - background: $background_div; - height: 60px; - a { - height: 100%; - width: (100% / 6); - } - div { - width: (100% * 4 / 6); - } - } - nav.mobile-foldable { - display: none; - background: $background_div; - color: $color_div; - a { - //background: $color_div; - //color: $background_div; - display: block; - } - } - nav.mobile-foldable.show { - display: block; - } + margin: 0; + padding: 0; + overflow: hidden; + min-height: 100%; + width: 100%; + height: 100%; - h1 { - text-align: center; - font-size: 50px; - } - - div.footer { - p,h1,h2,h3,h4,a { - font-size: initial; - } - a.suscribe-category-rss { - padding: 7px; - } - a.suscribe-category-rss,a.suscribe-category-rss > img { - width: 20px; - height: 20px; - } - } - } + div.site-wrapper { + display: table; + width: 100%; + height: 100%; + /* For at least Firefox */ + min-height: 100%; + color: $color; + background: $background; + filter: blur(10px); + background-size: cover; + overflow: hidden; + } + + div.page-contents { + position: absolute; + position: fixed; + overflow-y: scroll; + z-index: 2; + background: $background-page; + color: $color-page; + top: 0%; + left: 0%; + height: 100%; + + div.child-categories-mobile a { + padding-left: 2.5rem; + } + + width: 100%; + + img { + max-width: 100%; + margin-left: auto; + margin-right: auto; + display: block; + } + + table { + color: $background_div; + background: $color_div; + border: 3px solid $background_div; + border-collapse: collapse; + width: 100%; + + td, th { + font-size: 12px; + } + + table-layout: fixed; + } + + th, td { + border: 3px solid $background_div; + border-collapse: collapse; + padding-right: 10px; + margin: 0; + } + + div.description { + margin-top: 60px; + input { + display: block; + } + + word-wrap: break-word; + + div.suscribirse-rss { + img { + max-height: 300px; + } + } + + padding: 1%; + margin-left: 3%; + margin-right: 3%; + margin-bottom: 1%; + + div.articles { + display: flex; + flex-direction: row; + flex-wrap: wrap; + + div.image-container { + margin-left: 2.5%; + margin-top: 10px; + height: 95%; + width: 95%; + display: flex; + min-height: 130px; + justify-content: center; + align-items: center; + img { + max-height: 100%; + max-width: 100%; + min-width: 277px; + border: solid 1px black; + } + } + + a { + min-height: 90%; + width: 100%; + display: block; + text-decoration: none; + text-overflow: ellipsis; + margin-bottom: 30px; + + article { + word-wrap: break-word; + width: 90%; + height: 90%; + + p, h4, h3, h2 { + margin: 0px; + } + p { + font-size: 0.9rem; + } + + div.article-up-part { + height: 12em; + } + + div.article-down-part { + margin-top: 2em; + height: 9em; + display: flex; + align-items: end; + padding-bottom: 2em; + } + + padding: 5%; + padding-top: 1%; + background: $color_div; + color: $background_div; + box-shadow: 8px 8px 1px 0px #8ddfd6; + border: 3px solid black; + + &:hover { + background: $background_div; + color: $color_div; + } + + p.date { + text-align: right; + } + + p.author { + text-align: right; + } + } + } + } + + a.suscribe-category-rss { + background: $background_div; + width: 40px; + height: 40px; + padding: 10px; + border-radius: 5px; + display: inline-block; + + img { + width: 40px; + height: 40px; + } + } + } + + nav > a.menu-expand > img { + width: 30px; + height: 30px; + padding-top: 15px; + } + + nav > a > img.index-image-menu { + vertical-align: middle; + width: 50px; + height: 50px; + padding-bottom: 10px; + } + + nav.desktop { + display: none; + + a { + vertical-align: middle; + background: $background_div; + } + } + + nav { + overflow: auto; + display: block; + font-size: 25px; + margin: 0px; + + a.go-to-index img { + margin-top: 5%; + } + + a { + padding-left: 10px; + padding-right: 10px; + height: 100%; + text-decoration: none; + color: $color_div; + margin: 0; + + &:hover { + background: $color_div; + color: $background_div; + } + + &.selected { + background: $color_div; + color: $background_div; + } + } + + a.menu-expand { + padding-bottom: 9px; + + .open-menu-icon-hover { + display: none; + } + + &:hover { + .open-menu-icon-hover { + display: block; + } + + .open-menu-icon { + display: none; + } + } + } + } + + nav.mobile-shortcuts { + position: fixed; + display: flex; + width: 100%; + background: $background_div; + height: 60px; + + a { + height: 100%; + width: (100% / 6); + } + + div { + width: 100% * 4 / 6; + } + } + + nav.mobile-foldable { + display: none; + background: $background_div; + color: $color_div; + + a { + //background: $color_div; + //color: $background_div; + display: block; + } + } + + nav.mobile-foldable.show { + display: block; + } + + h1 { + text-align: center; + } + + div.footer { + p, h1, h2, h3, h4, a { + font-size: initial; + } + + a.suscribe-category-rss { + padding: 7px; + } + + a.suscribe-category-rss, a.suscribe-category-rss > img { + width: 20px; + height: 20px; + } + } + } +} + +@media (min-width: 450px) { + body { + div.page-contents { + table { + th, td { + font-size: 20px; + } + } + } + } +} +@media (min-width: 694px) { + body { + div.page-contents { + div.description { + + div.articles { + a { + &:nth-child(2n+1) { + margin-left: 0%; + } + width: 45%; + margin-left: 5%; + } + } + } + } + } } @media (min-width: 1100px) { - body { - div.page-contents { - th,td { - font-size: 40px; - } - nav.mobile-foldable,nav.mobile-foldable.show { - display: none; - } - div.description { - margin-left: 10%; - margin-right: 10%; - margin-top: auto; - } - nav.desktop { - display: block; - height: auto; - a { - display: table-cell; - img.index-image-menu { - padding-top: 15px; - } - } - } - nav.mobile-shortcuts { - display: none; - } - top: 2%; - left: 5%; - height: 96%; - width: 90%; - } - } + body { + div.page-contents { + nav.mobile-foldable, nav.mobile-foldable.show { + display: none; + } + + div.description { + margin-left: 10%; + margin-right: 10%; + } + + nav.desktop { + display: block; + height: auto; + + a { + display: table-cell; + + img.index-image-menu { + padding-top: 15px; + } + } + } + + nav.mobile-shortcuts { + display: none; + } + + top: 0%; + left: 5%; + height: 100%; + width: 90%; + } + } } -@media (min-width: 1222px) { - body { - div.page-contents { - div.description { - margin-top: auto; - div.articles { - a { - width: 45%; - margin-left: 5%; - } - } - } - } - } +@media (min-width: 1333px) { + body { + div.page-contents { + div.description { + + div.articles { + a { + &:nth-child(2n+1) { + margin-left: 3%; + } + &:nth-child(3n+1) { + margin-left: 0%; + } + width: 30%; + margin-left: 3%; + } + } + } + } + } } diff --git a/public/img/autobus-burguillos-tercer-mundo.generated.webp b/public/img/autobus-burguillos-tercer-mundo.generated.webp new file mode 100644 index 0000000..d6b9982 Binary files /dev/null and b/public/img/autobus-burguillos-tercer-mundo.generated.webp differ diff --git a/public/img/autobus-burguillos-tercer-mundo.jpg b/public/img/autobus-burguillos-tercer-mundo.jpg new file mode 100644 index 0000000..a6e6707 Binary files /dev/null and b/public/img/autobus-burguillos-tercer-mundo.jpg differ diff --git a/public/img/autobus-burguillos-tercer-mundo.webp b/public/img/autobus-burguillos-tercer-mundo.webp new file mode 100644 index 0000000..26c9af0 Binary files /dev/null and b/public/img/autobus-burguillos-tercer-mundo.webp differ diff --git a/public/img/autobus.webp b/public/img/autobus.webp new file mode 100644 index 0000000..7a00639 Binary files /dev/null and b/public/img/autobus.webp differ diff --git a/public/img/beluche.webp b/public/img/beluche.webp new file mode 100644 index 0000000..113c5dd Binary files /dev/null and b/public/img/beluche.webp differ diff --git a/public/img/bocaton-1.webp b/public/img/bocaton-1.webp new file mode 100644 index 0000000..d861e6f Binary files /dev/null and b/public/img/bocaton-1.webp differ diff --git a/public/img/bocaton-2.webp b/public/img/bocaton-2.webp new file mode 100644 index 0000000..2b54fbb Binary files /dev/null and b/public/img/bocaton-2.webp differ diff --git a/public/img/bocaton-3.webp b/public/img/bocaton-3.webp new file mode 100644 index 0000000..376761c Binary files /dev/null and b/public/img/bocaton-3.webp differ diff --git a/public/img/bocaton-4.webp b/public/img/bocaton-4.webp new file mode 100644 index 0000000..531bbb3 Binary files /dev/null and b/public/img/bocaton-4.webp differ diff --git a/public/img/bocaton-preview.webp b/public/img/bocaton-preview.webp new file mode 100644 index 0000000..a13bcae Binary files /dev/null and b/public/img/bocaton-preview.webp differ diff --git a/public/img/burguillos.webp b/public/img/burguillos.webp new file mode 100644 index 0000000..a022ed1 Binary files /dev/null and b/public/img/burguillos.webp differ diff --git a/public/img/chapata-pizza.webp b/public/img/chapata-pizza.webp new file mode 100644 index 0000000..c79b863 Binary files /dev/null and b/public/img/chapata-pizza.webp differ diff --git a/public/img/cristobal-preview.webp b/public/img/cristobal-preview.webp new file mode 100644 index 0000000..0e85091 Binary files /dev/null and b/public/img/cristobal-preview.webp differ diff --git a/public/img/cristobal.webp b/public/img/cristobal.webp new file mode 100644 index 0000000..e863b4f Binary files /dev/null and b/public/img/cristobal.webp differ diff --git a/public/img/diaspora-article-image-1.webp b/public/img/diaspora-article-image-1.webp new file mode 100644 index 0000000..39a5b7c Binary files /dev/null and b/public/img/diaspora-article-image-1.webp differ diff --git a/public/img/diaspora-article-image-10.webp b/public/img/diaspora-article-image-10.webp new file mode 100644 index 0000000..403a355 Binary files /dev/null and b/public/img/diaspora-article-image-10.webp differ diff --git a/public/img/diaspora-article-image-2.webp b/public/img/diaspora-article-image-2.webp new file mode 100644 index 0000000..ce67e9c Binary files /dev/null and b/public/img/diaspora-article-image-2.webp differ diff --git a/public/img/diaspora-article-image-3.webp b/public/img/diaspora-article-image-3.webp new file mode 100644 index 0000000..9120570 Binary files /dev/null and b/public/img/diaspora-article-image-3.webp differ diff --git a/public/img/diaspora-article-image-4.webp b/public/img/diaspora-article-image-4.webp new file mode 100644 index 0000000..4c78109 Binary files /dev/null and b/public/img/diaspora-article-image-4.webp differ diff --git a/public/img/diaspora-article-image-5.webp b/public/img/diaspora-article-image-5.webp new file mode 100644 index 0000000..37ef687 Binary files /dev/null and b/public/img/diaspora-article-image-5.webp differ diff --git a/public/img/diaspora-article-image-6.webp b/public/img/diaspora-article-image-6.webp new file mode 100644 index 0000000..3d18e7d Binary files /dev/null and b/public/img/diaspora-article-image-6.webp differ diff --git a/public/img/diaspora-article-image-7.webp b/public/img/diaspora-article-image-7.webp new file mode 100644 index 0000000..955105a Binary files /dev/null and b/public/img/diaspora-article-image-7.webp differ diff --git a/public/img/diaspora-article-image-8.webp b/public/img/diaspora-article-image-8.webp new file mode 100644 index 0000000..ae42b28 Binary files /dev/null and b/public/img/diaspora-article-image-8.webp differ diff --git a/public/img/diaspora-article-image-9.webp b/public/img/diaspora-article-image-9.webp new file mode 100644 index 0000000..6229139 Binary files /dev/null and b/public/img/diaspora-article-image-9.webp differ diff --git a/public/img/diaspora-article-preview.webp b/public/img/diaspora-article-preview.webp new file mode 100644 index 0000000..80a79c1 Binary files /dev/null and b/public/img/diaspora-article-preview.webp differ diff --git a/public/img/diaspora.webp b/public/img/diaspora.webp new file mode 100644 index 0000000..1e9ea79 Binary files /dev/null and b/public/img/diaspora.webp differ diff --git a/public/img/duran.webp b/public/img/duran.webp new file mode 100644 index 0000000..afe611c Binary files /dev/null and b/public/img/duran.webp differ diff --git a/public/img/eduardo-trasierra-preview.webp b/public/img/eduardo-trasierra-preview.webp new file mode 100644 index 0000000..e1da623 Binary files /dev/null and b/public/img/eduardo-trasierra-preview.webp differ diff --git a/public/img/eduardo-trasierra.webp b/public/img/eduardo-trasierra.webp new file mode 100644 index 0000000..e36d7ae Binary files /dev/null and b/public/img/eduardo-trasierra.webp differ diff --git a/public/img/feminismo.webp b/public/img/feminismo.webp new file mode 100644 index 0000000..f09dc84 Binary files /dev/null and b/public/img/feminismo.webp differ diff --git a/public/img/fibra-cortada.jpg b/public/img/fibra-cortada.jpg new file mode 100644 index 0000000..90aec1f Binary files /dev/null and b/public/img/fibra-cortada.jpg differ diff --git a/public/img/fibra-cortada.webp b/public/img/fibra-cortada.webp new file mode 100644 index 0000000..9e1e723 Binary files /dev/null and b/public/img/fibra-cortada.webp differ diff --git a/public/img/fogon-de-segovia.jpg b/public/img/fogon-de-segovia.jpg new file mode 100644 index 0000000..75958f3 Binary files /dev/null and b/public/img/fogon-de-segovia.jpg differ diff --git a/public/img/genuino.webp b/public/img/genuino.webp new file mode 100644 index 0000000..2cba2f1 Binary files /dev/null and b/public/img/genuino.webp differ diff --git a/public/img/hamburger-menu-purple.png b/public/img/hamburger-menu-purple.png new file mode 100644 index 0000000..7d131af Binary files /dev/null and b/public/img/hamburger-menu-purple.png differ diff --git a/public/img/hamburger-menu-purple.webp b/public/img/hamburger-menu-purple.webp new file mode 100644 index 0000000..d2fac5e Binary files /dev/null and b/public/img/hamburger-menu-purple.webp differ diff --git a/public/img/hamburger-menu-yellow.png b/public/img/hamburger-menu-yellow.png new file mode 100644 index 0000000..bdb2abb Binary files /dev/null and b/public/img/hamburger-menu-yellow.png differ diff --git a/public/img/hamburger-menu-yellow.webp b/public/img/hamburger-menu-yellow.webp new file mode 100644 index 0000000..3403096 Binary files /dev/null and b/public/img/hamburger-menu-yellow.webp differ diff --git a/public/img/hamburgueseria-la-ermita.webp b/public/img/hamburgueseria-la-ermita.webp new file mode 100644 index 0000000..9313046 Binary files /dev/null and b/public/img/hamburgueseria-la-ermita.webp differ diff --git a/public/img/mairami-1.webp b/public/img/mairami-1.webp new file mode 100644 index 0000000..de03187 Binary files /dev/null and b/public/img/mairami-1.webp differ diff --git a/public/img/mairami-2.webp b/public/img/mairami-2.webp new file mode 100644 index 0000000..d95ef1c Binary files /dev/null and b/public/img/mairami-2.webp differ diff --git a/public/img/mairami-cuentacuentos/1.webp b/public/img/mairami-cuentacuentos/1.webp new file mode 100644 index 0000000..a601896 Binary files /dev/null and b/public/img/mairami-cuentacuentos/1.webp differ diff --git a/public/img/mairami-cuentacuentos/2.webp b/public/img/mairami-cuentacuentos/2.webp new file mode 100644 index 0000000..aa6168d Binary files /dev/null and b/public/img/mairami-cuentacuentos/2.webp differ diff --git a/public/img/mairami-cuentacuentos/3.webp b/public/img/mairami-cuentacuentos/3.webp new file mode 100644 index 0000000..082c89a Binary files /dev/null and b/public/img/mairami-cuentacuentos/3.webp differ diff --git a/public/img/mairami-cuentacuentos/4.webp b/public/img/mairami-cuentacuentos/4.webp new file mode 100644 index 0000000..b800a5e Binary files /dev/null and b/public/img/mairami-cuentacuentos/4.webp differ diff --git a/public/img/mairami-cuentacuentos/5.webp b/public/img/mairami-cuentacuentos/5.webp new file mode 100644 index 0000000..d2de2f7 Binary files /dev/null and b/public/img/mairami-cuentacuentos/5.webp differ diff --git a/public/img/mairami-preview.webp b/public/img/mairami-preview.webp new file mode 100644 index 0000000..ecb74ed Binary files /dev/null and b/public/img/mairami-preview.webp differ diff --git a/public/img/menu.webp b/public/img/menu.webp new file mode 100644 index 0000000..d3ff5f8 Binary files /dev/null and b/public/img/menu.webp differ diff --git a/public/img/noemi.jpg b/public/img/noemi.jpg new file mode 100644 index 0000000..2c1fad1 Binary files /dev/null and b/public/img/noemi.jpg differ diff --git a/public/img/noemi.webp b/public/img/noemi.webp new file mode 100644 index 0000000..62b1d29 Binary files /dev/null and b/public/img/noemi.webp differ diff --git a/public/img/parque_patos.webp b/public/img/parque_patos.webp new file mode 100644 index 0000000..1dbca6c Binary files /dev/null and b/public/img/parque_patos.webp differ diff --git a/public/img/pepin.webp b/public/img/pepin.webp new file mode 100644 index 0000000..5274adc Binary files /dev/null and b/public/img/pepin.webp differ diff --git a/public/img/pizzeria-los-naranjos-preview.png b/public/img/pizzeria-los-naranjos-preview.png new file mode 100644 index 0000000..77a6763 Binary files /dev/null and b/public/img/pizzeria-los-naranjos-preview.png differ diff --git a/public/img/pizzeria-los-naranjos-preview.webp b/public/img/pizzeria-los-naranjos-preview.webp new file mode 100644 index 0000000..32bfed3 Binary files /dev/null and b/public/img/pizzeria-los-naranjos-preview.webp differ diff --git a/public/img/pizzeria-los-naranjos.jpg b/public/img/pizzeria-los-naranjos.jpg new file mode 100644 index 0000000..91bf20f Binary files /dev/null and b/public/img/pizzeria-los-naranjos.jpg differ diff --git a/public/img/pizzeria-los-naranjos.webp b/public/img/pizzeria-los-naranjos.webp new file mode 100644 index 0000000..45475f3 Binary files /dev/null and b/public/img/pizzeria-los-naranjos.webp differ diff --git a/public/img/plataforma-nala-preview.webp b/public/img/plataforma-nala-preview.webp new file mode 100644 index 0000000..80fdc2a Binary files /dev/null and b/public/img/plataforma-nala-preview.webp differ diff --git a/public/img/plataforma-nala.webp b/public/img/plataforma-nala.webp new file mode 100644 index 0000000..8978854 Binary files /dev/null and b/public/img/plataforma-nala.webp differ diff --git a/public/img/policlinica-burguillos-1.webp b/public/img/policlinica-burguillos-1.webp new file mode 100644 index 0000000..8688757 Binary files /dev/null and b/public/img/policlinica-burguillos-1.webp differ diff --git a/public/img/policlinica-burguillos-2.webp b/public/img/policlinica-burguillos-2.webp new file mode 100644 index 0000000..304fbb7 Binary files /dev/null and b/public/img/policlinica-burguillos-2.webp differ diff --git a/public/img/policlinica-burguillos-preview.webp b/public/img/policlinica-burguillos-preview.webp new file mode 100644 index 0000000..13b4c9b Binary files /dev/null and b/public/img/policlinica-burguillos-preview.webp differ diff --git a/public/img/portada-certamen-teatro-preview.webp b/public/img/portada-certamen-teatro-preview.webp new file mode 100644 index 0000000..8c8ec8d Binary files /dev/null and b/public/img/portada-certamen-teatro-preview.webp differ diff --git a/public/img/portada-certamen-teatro.webp b/public/img/portada-certamen-teatro.webp new file mode 100644 index 0000000..27cb849 Binary files /dev/null and b/public/img/portada-certamen-teatro.webp differ diff --git a/public/img/poster-macrame-preview.webp b/public/img/poster-macrame-preview.webp new file mode 100644 index 0000000..36bdbd4 Binary files /dev/null and b/public/img/poster-macrame-preview.webp differ diff --git a/public/img/poster-macrame.webp b/public/img/poster-macrame.webp new file mode 100644 index 0000000..2efddcf Binary files /dev/null and b/public/img/poster-macrame.webp differ diff --git a/public/img/refugees-welcome.webp b/public/img/refugees-welcome.webp new file mode 100644 index 0000000..7ea9508 Binary files /dev/null and b/public/img/refugees-welcome.webp differ diff --git a/public/img/rss/1.webp b/public/img/rss/1.webp new file mode 100644 index 0000000..bb12134 Binary files /dev/null and b/public/img/rss/1.webp differ diff --git a/public/img/rss/2.webp b/public/img/rss/2.webp new file mode 100644 index 0000000..be78474 Binary files /dev/null and b/public/img/rss/2.webp differ diff --git a/public/img/rss/3.webp b/public/img/rss/3.webp new file mode 100644 index 0000000..66cac20 Binary files /dev/null and b/public/img/rss/3.webp differ diff --git a/public/img/rss/4.webp b/public/img/rss/4.webp new file mode 100644 index 0000000..9c404c8 Binary files /dev/null and b/public/img/rss/4.webp differ diff --git a/public/img/rss/5.webp b/public/img/rss/5.webp new file mode 100644 index 0000000..8a56579 Binary files /dev/null and b/public/img/rss/5.webp differ diff --git a/public/img/rss/6.webp b/public/img/rss/6.webp new file mode 100644 index 0000000..640aad2 Binary files /dev/null and b/public/img/rss/6.webp differ diff --git a/public/img/rss/7.webp b/public/img/rss/7.webp new file mode 100644 index 0000000..29dfb66 Binary files /dev/null and b/public/img/rss/7.webp differ diff --git a/public/img/rss/8.webp b/public/img/rss/8.webp new file mode 100644 index 0000000..c4310f7 Binary files /dev/null and b/public/img/rss/8.webp differ diff --git a/public/img/rss/9.webp b/public/img/rss/9.webp new file mode 100644 index 0000000..b53d917 Binary files /dev/null and b/public/img/rss/9.webp differ diff --git a/public/img/sahara-adopta.webp b/public/img/sahara-adopta.webp new file mode 100644 index 0000000..ad10b6a Binary files /dev/null and b/public/img/sahara-adopta.webp differ diff --git a/public/img/silencio-se-piensa-1.webp b/public/img/silencio-se-piensa-1.webp new file mode 100644 index 0000000..af6e24a Binary files /dev/null and b/public/img/silencio-se-piensa-1.webp differ diff --git a/public/img/silencio-se-piensa-preview.webp b/public/img/silencio-se-piensa-preview.webp new file mode 100644 index 0000000..8fc6df7 Binary files /dev/null and b/public/img/silencio-se-piensa-preview.webp differ diff --git a/public/img/xmpp-1.webp b/public/img/xmpp-1.webp new file mode 100644 index 0000000..f325724 Binary files /dev/null and b/public/img/xmpp-1.webp differ diff --git a/public/img/xmpp-2.webp b/public/img/xmpp-2.webp new file mode 100644 index 0000000..91e68af Binary files /dev/null and b/public/img/xmpp-2.webp differ diff --git a/public/img/xmpp-3.webp b/public/img/xmpp-3.webp new file mode 100644 index 0000000..5d0c27d Binary files /dev/null and b/public/img/xmpp-3.webp differ diff --git a/public/img/xmpp-4.webp b/public/img/xmpp-4.webp new file mode 100644 index 0000000..761f388 Binary files /dev/null and b/public/img/xmpp-4.webp differ diff --git a/public/img/xmpp-preview.webp b/public/img/xmpp-preview.webp new file mode 100644 index 0000000..8f3981e Binary files /dev/null and b/public/img/xmpp-preview.webp differ diff --git a/public/js/bundle.js b/public/js/bundle.js new file mode 100644 index 0000000..d953138 --- /dev/null +++ b/public/js/bundle.js @@ -0,0 +1,118 @@ +/* + * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). + * This devtool is neither made for production nor for readable output files. + * It uses "eval()" calls to create a separate source file in the browser devtools. + * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) + * or disable the default devtool with "devtool: false". + * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). + */ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ "./js-src/index.ts": +/*!*************************!*\ + !*** ./js-src/index.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var tablesort__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tablesort */ \"./node_modules/tablesort/src/tablesort.js\");\n/* harmony import */ var tablesort__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tablesort__WEBPACK_IMPORTED_MODULE_0__);\n\n\nwindow.Tablesort = __webpack_require__(/*! tablesort */ \"./node_modules/tablesort/src/tablesort.js\");\n__webpack_require__(/*! tablesort/src/sorts/tablesort.number */ \"./node_modules/tablesort/src/sorts/tablesort.number.js\");\n\nwindow.onload = () => {\n const menu_expand = document.querySelector('a.menu-expand');\n const mobile_foldable = document.querySelector('nav.mobile-foldable');\n const tables = document.querySelectorAll('table')\n\n if (menu_expand !== null && mobile_foldable !== null) {\n menu_expand.addEventListener('click', () => {\n mobile_foldable.classList.toggle('show');\n });\n }\n\n for (const table of tables) {\n const header = table.querySelector('tr');\n if (header !== null) {\n header.setAttribute('data-sort-method', 'none')\n for (const th of header.querySelectorAll('th')) {\n if (th.getAttribute('data-sort-method') == null) {\n th.setAttribute('data-sort-method', 'thead')\n }\n }\n }\n new (tablesort__WEBPACK_IMPORTED_MODULE_0___default())(table)\n }\n};\n\n\n//# sourceURL=webpack://BurguillosInfo/./js-src/index.ts?"); + +/***/ }), + +/***/ "./node_modules/tablesort/src/sorts/tablesort.number.js": +/*!**************************************************************!*\ + !*** ./node_modules/tablesort/src/sorts/tablesort.number.js ***! + \**************************************************************/ +/***/ (() => { + +eval("(function(){\n var cleanNumber = function(i) {\n return i.replace(/[^\\-?0-9.]/g, '');\n },\n\n compareNumber = function(a, b) {\n a = parseFloat(a);\n b = parseFloat(b);\n\n a = isNaN(a) ? 0 : a;\n b = isNaN(b) ? 0 : b;\n\n return a - b;\n };\n\n Tablesort.extend('number', function(item) {\n return item.match(/^[-+]?[£\\x24Û¢´€]?\\d+\\s*([,\\.]\\d{0,2})/) || // Prefixed currency\n item.match(/^[-+]?\\d+\\s*([,\\.]\\d{0,2})?[£\\x24Û¢´€]/) || // Suffixed currency\n item.match(/^[-+]?(\\d)*-?([,\\.]){0,1}-?(\\d)+([E,e][\\-+][\\d]+)?%?$/); // Number\n }, function(a, b) {\n a = cleanNumber(a);\n b = cleanNumber(b);\n\n return compareNumber(b, a);\n });\n}());\n\n\n//# sourceURL=webpack://BurguillosInfo/./node_modules/tablesort/src/sorts/tablesort.number.js?"); + +/***/ }), + +/***/ "./node_modules/tablesort/src/tablesort.js": +/*!*************************************************!*\ + !*** ./node_modules/tablesort/src/tablesort.js ***! + \*************************************************/ +/***/ ((module) => { + +eval(";(function() {\n function Tablesort(el, options) {\n if (!(this instanceof Tablesort)) return new Tablesort(el, options);\n\n if (!el || el.tagName !== 'TABLE') {\n throw new Error('Element must be a table');\n }\n this.init(el, options || {});\n }\n\n var sortOptions = [];\n\n var createEvent = function(name) {\n var evt;\n\n if (!window.CustomEvent || typeof window.CustomEvent !== 'function') {\n evt = document.createEvent('CustomEvent');\n evt.initCustomEvent(name, false, false, undefined);\n } else {\n evt = new CustomEvent(name);\n }\n\n return evt;\n };\n\n var getInnerText = function(el,options) {\n return el.getAttribute(options.sortAttribute || 'data-sort') || el.textContent || el.innerText || '';\n };\n\n // Default sort method if no better sort method is found\n var caseInsensitiveSort = function(a, b) {\n a = a.trim().toLowerCase();\n b = b.trim().toLowerCase();\n\n if (a === b) return 0;\n if (a < b) return 1;\n\n return -1;\n };\n\n var getCellByKey = function(cells, key) {\n return [].slice.call(cells).find(function(cell) {\n return cell.getAttribute('data-sort-column-key') === key;\n });\n };\n\n // Stable sort function\n // If two elements are equal under the original sort function,\n // then there relative order is reversed\n var stabilize = function(sort, antiStabilize) {\n return function(a, b) {\n var unstableResult = sort(a.td, b.td);\n\n if (unstableResult === 0) {\n if (antiStabilize) return b.index - a.index;\n return a.index - b.index;\n }\n\n return unstableResult;\n };\n };\n\n Tablesort.extend = function(name, pattern, sort) {\n if (typeof pattern !== 'function' || typeof sort !== 'function') {\n throw new Error('Pattern and sort must be a function');\n }\n\n sortOptions.push({\n name: name,\n pattern: pattern,\n sort: sort\n });\n };\n\n Tablesort.prototype = {\n\n init: function(el, options) {\n var that = this,\n firstRow,\n defaultSort,\n i,\n cell;\n\n that.table = el;\n that.thead = false;\n that.options = options;\n\n if (el.rows && el.rows.length > 0) {\n if (el.tHead && el.tHead.rows.length > 0) {\n for (i = 0; i < el.tHead.rows.length; i++) {\n if (el.tHead.rows[i].getAttribute('data-sort-method') === 'thead') {\n firstRow = el.tHead.rows[i];\n break;\n }\n }\n if (!firstRow) {\n firstRow = el.tHead.rows[el.tHead.rows.length - 1];\n }\n that.thead = true;\n } else {\n firstRow = el.rows[0];\n }\n }\n\n if (!firstRow) return;\n\n var onClick = function() {\n if (that.current && that.current !== this) {\n that.current.removeAttribute('aria-sort');\n }\n\n that.current = this;\n that.sortTable(this);\n };\n\n // Assume first row is the header and attach a click handler to each.\n for (i = 0; i < firstRow.cells.length; i++) {\n cell = firstRow.cells[i];\n cell.setAttribute('role','columnheader');\n if (cell.getAttribute('data-sort-method') !== 'none') {\n cell.tabindex = 0;\n cell.addEventListener('click', onClick, false);\n\n if (cell.getAttribute('data-sort-default') !== null) {\n defaultSort = cell;\n }\n }\n }\n\n if (defaultSort) {\n that.current = defaultSort;\n that.sortTable(defaultSort);\n }\n },\n\n sortTable: function(header, update) {\n var that = this,\n columnKey = header.getAttribute('data-sort-column-key'),\n column = header.cellIndex,\n sortFunction = caseInsensitiveSort,\n item = '',\n items = [],\n i = that.thead ? 0 : 1,\n sortMethod = header.getAttribute('data-sort-method'),\n sortOrder = header.getAttribute('aria-sort');\n\n that.table.dispatchEvent(createEvent('beforeSort'));\n\n // If updating an existing sort, direction should remain unchanged.\n if (!update) {\n if (sortOrder === 'ascending') {\n sortOrder = 'descending';\n } else if (sortOrder === 'descending') {\n sortOrder = 'ascending';\n } else {\n sortOrder = that.options.descending ? 'descending' : 'ascending';\n }\n\n header.setAttribute('aria-sort', sortOrder);\n }\n\n if (that.table.rows.length < 2) return;\n\n // If we force a sort method, it is not necessary to check rows\n if (!sortMethod) {\n var cell;\n while (items.length < 3 && i < that.table.tBodies[0].rows.length) {\n if(columnKey) {\n cell = getCellByKey(that.table.tBodies[0].rows[i].cells, columnKey);\n } else {\n cell = that.table.tBodies[0].rows[i].cells[column];\n }\n\n // Treat missing cells as empty cells\n item = cell ? getInnerText(cell,that.options) : \"\";\n\n item = item.trim();\n\n if (item.length > 0) {\n items.push(item);\n }\n\n i++;\n }\n\n if (!items) return;\n }\n\n for (i = 0; i < sortOptions.length; i++) {\n item = sortOptions[i];\n\n if (sortMethod) {\n if (item.name === sortMethod) {\n sortFunction = item.sort;\n break;\n }\n } else if (items.every(item.pattern)) {\n sortFunction = item.sort;\n break;\n }\n }\n\n that.col = column;\n\n for (i = 0; i < that.table.tBodies.length; i++) {\n var newRows = [],\n noSorts = {},\n j,\n totalRows = 0,\n noSortsSoFar = 0;\n\n if (that.table.tBodies[i].rows.length < 2) continue;\n\n for (j = 0; j < that.table.tBodies[i].rows.length; j++) {\n var cell;\n\n item = that.table.tBodies[i].rows[j];\n if (item.getAttribute('data-sort-method') === 'none') {\n // keep no-sorts in separate list to be able to insert\n // them back at their original position later\n noSorts[totalRows] = item;\n } else {\n if (columnKey) {\n cell = getCellByKey(item.cells, columnKey);\n } else {\n cell = item.cells[that.col];\n }\n // Save the index for stable sorting\n newRows.push({\n tr: item,\n td: cell ? getInnerText(cell,that.options) : '',\n index: totalRows\n });\n }\n totalRows++;\n }\n // Before we append should we reverse the new array or not?\n // If we reverse, the sort needs to be `anti-stable` so that\n // the double negatives cancel out\n if (sortOrder === 'descending') {\n newRows.sort(stabilize(sortFunction, true));\n } else {\n newRows.sort(stabilize(sortFunction, false));\n newRows.reverse();\n }\n\n // append rows that already exist rather than creating new ones\n for (j = 0; j < totalRows; j++) {\n if (noSorts[j]) {\n // We have a no-sort row for this position, insert it here.\n item = noSorts[j];\n noSortsSoFar++;\n } else {\n item = newRows[j - noSortsSoFar].tr;\n }\n\n // appendChild(x) moves x if already present somewhere else in the DOM\n that.table.tBodies[i].appendChild(item);\n }\n }\n\n that.table.dispatchEvent(createEvent('afterSort'));\n },\n\n refresh: function() {\n if (this.current !== undefined) {\n this.sortTable(this.current, true);\n }\n }\n };\n\n if ( true && module.exports) {\n module.exports = Tablesort;\n } else {\n window.Tablesort = Tablesort;\n }\n})();\n\n\n//# sourceURL=webpack://BurguillosInfo/./node_modules/tablesort/src/tablesort.js?"); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +/******/ +/******/ // startup +/******/ // Load entry module and return exports +/******/ // This entry module can't be inlined because the eval devtool is used. +/******/ var __webpack_exports__ = __webpack_require__("./js-src/index.ts"); +/******/ +/******/ })() +; \ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt deleted file mode 100644 index c5ca693..0000000 --- a/public/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -User-Agent: * -Disallow: /stats -Disallow: /stats/* diff --git a/templates/404.html.ep b/templates/404.html.ep index ff8aa5b..f507043 100644 --- a/templates/404.html.ep +++ b/templates/404.html.ep @@ -1,7 +1,7 @@ % use Mojo::Util; % use BurguillosInfo::Categories; -% layout 'default', current_slug => undef, categories => BurguillosInfo::Categories->new->Retrieve; +% layout 'default', current_category_slug => undef, categories => BurguillosInfo::Categories->new->Retrieve;

    Esta página no existe.

    -

    Si un enlace te ha llevado aquí, reporta el error a los administradores.

    +

    Si un enlace te ha llevado aquí, reporta el error a los administradores.

    diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep index 590aefd..aa543f3 100644 --- a/templates/layouts/default.html.ep +++ b/templates/layouts/default.html.ep @@ -1,59 +1,48 @@ +% my $categories = stash 'categories'; +% my $current_category_slug = stash 'current_category_slug'; +% my $description_og = stash 'description_og'; +% $description_og =~ s/\s+/ /g; +% $description_og = substr $description_og, 0, 157; +% $description_og =~ s/\s\S+$//; +% $description_og.='...'; +% my $base_url = config 'base_url'; - - + +% my $css_version = config 'css_version'; + <%= title %> - + - + % my $ogimage = stash 'ogimage'; % my $user_agent = stash 'useragent'; -% if (defined $ogimage && $user_agent !~ /TelegramBot/) { - + +% if (defined $ogimage) { + + % } else { - + + % } - + +
    - - - - +%= include 'page/_desktop_menu', categories => $categories, current_category_slug => $current_category_slug +%= include 'page/_mobile_menu', categories => $categories <%= content %>
    diff --git a/templates/layouts/stats.html.ep b/templates/layouts/stats.html.ep index ec8a666..6024312 100644 --- a/templates/layouts/stats.html.ep +++ b/templates/layouts/stats.html.ep @@ -1,6 +1,7 @@ + @@ -8,7 +9,7 @@
    <%= content %>
    diff --git a/templates/metrics/stats.html.ep b/templates/metrics/stats.html.ep index a4291c0..482da25 100644 --- a/templates/metrics/stats.html.ep +++ b/templates/metrics/stats.html.ep @@ -1,25 +1,61 @@ % layout 'stats'; +% my $base_url = config 'base_url';

    Stats

    -

    Unique visitors <%=$tracking_data->{unique_ips}%>

    Unique visitors last 24 hours <%=$tracking_data->{unique_ips_last_24_hours}%>

    Unique visitors last week <%=$tracking_data->{unique_ips_last_week}%>

    Unique visitors last month <%=$tracking_data->{unique_ips_last_month}%>

    +

    Ver datos sin extensiones.

    +

    Ver todo.

    - - - + + + + + + + % for my $row (@$tracking_by_url) { - + + + + + %}
    PathVisitors 24hVisitors weekVisitors monthVisitors 1hVisitors 3hVisitors 6hVisitors 12hVisitors 24hVisitors weekVisitors month
    <%=$row->{path}%><%="${base_url}$row->{path}"%><%=$row->{unique_ips_last_1_hour}%><%=$row->{unique_ips_last_3_hours}%><%=$row->{unique_ips_last_6_hours}%><%=$row->{unique_ips_last_12_hours}%> <%=$row->{unique_ips_last_24_hours}%> <%=$row->{unique_ips_last_week}%> <%=$row->{unique_ips_last_month}%>
    +

    Google data.

    + + + + + + + + + + + +% for my $row (@$google_data) { + + + + + + + + + + +%} +
    PathVisitors 1hVisitors 3hVisitors 6hVisitors 12hVisitors 24hVisitors weekVisitors month
    <%="${base_url}$row->{path}"%><%=$row->{unique_ips_last_1_hour}%><%=$row->{unique_ips_last_3_hours}%><%=$row->{unique_ips_last_6_hours}%><%=$row->{unique_ips_last_12_hours}%><%=$row->{unique_ips_last_24_hours}%><%=$row->{unique_ips_last_week}%><%=$row->{unique_ips_last_month}%>
    +
    diff --git a/templates/page/_desktop_menu.html.ep b/templates/page/_desktop_menu.html.ep new file mode 100644 index 0000000..33c4013 --- /dev/null +++ b/templates/page/_desktop_menu.html.ep @@ -0,0 +1,24 @@ +% my $categories = stash 'categories'; +% my $current_category_slug = stash 'current_category_slug'; + + diff --git a/templates/page/_list_posts.html.ep b/templates/page/_list_posts.html.ep new file mode 100644 index 0000000..5243efd --- /dev/null +++ b/templates/page/_list_posts.html.ep @@ -0,0 +1,30 @@ +% my $posts = stash 'posts'; +

    Artículos

    + diff --git a/templates/page/_mobile_menu.html.ep b/templates/page/_mobile_menu.html.ep new file mode 100644 index 0000000..bfa88d9 --- /dev/null +++ b/templates/page/_mobile_menu.html.ep @@ -0,0 +1,24 @@ +% my $categories = stash 'categories'; + + diff --git a/templates/page/attribute.html.ep b/templates/page/attribute.html.ep new file mode 100644 index 0000000..aea06c7 --- /dev/null +++ b/templates/page/attribute.html.ep @@ -0,0 +1,20 @@ +% use Data::Dumper; +% use DateTime::Format::ISO8601; +% +% use Mojo::DOM; +% use Mojo::Util; +% +% use BurguillosInfo::Posts; +% +% my $category = stash 'category'; +% my $attribute = stash 'attribute'; +% my $description_og = '
    '.$attribute->{description}.'
    '; +% $description_og = Mojo::DOM->new($description_og)->all_text; +% my $posts = stash 'posts'; +% layout 'default', current_category_slug => $category->{slug}, description_og => $description_og; +% title $attribute->{title}; +
    +

    <%= $attribute->{title} %>

    + <%== $attribute->{description} %> +%= include 'page/_list_posts', posts => $posts; +
    diff --git a/templates/page/index.html.ep b/templates/page/index.html.ep index 03b64d2..d1be0bc 100644 --- a/templates/page/index.html.ep +++ b/templates/page/index.html.ep @@ -1,44 +1,34 @@ +% use Data::Dumper; % use DateTime::Format::ISO8601; +% use Mojo::DOM; % % use Mojo::DOM; % use Mojo::Util; % % use BurguillosInfo::Posts; % -% layout 'default', current_slug => $current_category->{slug}; +% my $description_og = '
    '.$current_category->{description}.'
    '; +% $description_og = Mojo::DOM->new($description_og)->all_text; +% layout 'default', current_category_slug => $current_category->{slug}, description_og => $description_og; % title $current_category->{title};
    -

    <%= $current_category->{title} %>

    +

    <%= $current_category->{title} %>

    <%== $current_category->{description} %> -

    Artículos

    -
    -% my ($cached_posts_by_category) = BurguillosInfo::Posts->new->Retrieve; -% my $category_post = $cached_posts_by_category->{$current_category->{slug}}; -% if (defined $category_post) { -% for my $post (@$category_post) { - -
    <% - my $date_article = DateTime::Format::ISO8601->parse_datetime($post->{date}); - $date_article->set_time_zone('Europe/Madrid'); - %>

    <%= ''.$date_article %>

    <% - if (defined $post->{image}) { - %>Portada de <%=$post->{title}%><% - } - %>

    <%=$post->{title}%>

    <% - my $xml = Mojo::DOM->new($post->{content}); - my $text = $xml->all_text; - if (length($text) > 120) { - $text = substr($text, 0, 100).'...'; - } - %>

    <%=$text%>

    Escrito por <%=$post->{author}%>

    -
    -% } -% } else { -

    Parece que aun no hay artículos.

    +% my $children_categories = $current_category->{children}; +% my $attributes = $current_category->{attributes}; +% if (@$children_categories || %$attributes) { +

    Quizás te interese.

    +% for my $child_category (@$children_categories) { +

    <%==$child_category->{title}%>

    +% } +% for my $attribute_slug (keys %$attributes) { +% my $attribute = $attributes->{$attribute_slug}; +

    {slug}/atributo/$attribute->{identifier}"%>"><%==$attribute->{menu_text}%>

    +% } % } - -
    -

    Suscribete a esta categoría.

    +% my ($category_posts) = BurguillosInfo::Posts->new->RetrieveAllPostsForCategory($current_category->{slug}); +%= include 'page/_list_posts', posts => $category_posts; +

    Suscribete a esta categoría.

    Icono de suscripción rss diff --git a/templates/page/post.html.ep b/templates/page/post.html.ep index 8a1dcbd..87d51af 100644 --- a/templates/page/post.html.ep +++ b/templates/page/post.html.ep @@ -6,10 +6,13 @@ % use BurguillosInfo::Posts; % use BurguillosInfo::Categories; % my $categories = BurguillosInfo::Categories->new->Retrieve; -% layout 'default', current_slug => $current_category->{slug}, categories => $categories; +% my $description_og = '
    '.$post->{content}.'
    '; +% $description_og = Mojo::DOM->new($description_og)->all_text; +% my $base_url = config 'base_url'; +% layout 'default', current_category_slug => $current_category->{slug}, categories => $categories, description_og => $description_og, ogimage => "$base_url/posts/$post->{slug}-preview.png?v=4"; % title $post->{title};
    -

    <%= $post->{title} %>

    +

    <%= $post->{title} %>

    % my $user_agent = stash 'useragent'; % if ($user_agent !~ /LinkedInBot/) { <%== $post->{content} %> diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..70bfdfd --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "outDir": "./public/js/", + "noImplicitAny": true, + "module": "es2020", + "target": "es2020", + "allowJs": true, + "moduleResolution": "node", + "strictNullChecks": true, + "baseUrl": ".", + "paths": { + "@burguillosinfo/*": ["js-src/*"], + "/*": ["js-src/*"] + }, + "plugins": [ + { + "transform": "typescript-transform-paths" + }, + { + "transform": "typescript-transform-paths", + "afterDeclarations": true + } + ] + }, + "include": [ + "js-src/*.ts", "js-src/*/*.ts" + ] +} diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..a4a3f8a --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,28 @@ +const path = require('path') + +module.exports = { + entry: './js-src/index.ts', + mode: 'development', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'public/js/') + }, + resolve: { + extensions: ['.js', '.ts'], + roots: [ + path.resolve(__dirname, 'js-src/') + ], + alias: { + '@burguillosinfo': path.resolve(__dirname, 'js-src') + } + }, + module: { + rules: [ + { + test: /\.jpe?g|png$/, + exclude: /node_modules/, + use: ['url-loader', 'file-loader'] + } + ] + } +}