Compare commits

...

12 commits

Author SHA1 Message Date
f16745d9ad Inicializar inicio
All checks were successful
continuous-integration/woodpecker the build was successful
2021-10-11 16:18:21 -03:00
a439056607 Usar tabs para listas 2021-10-11 16:17:24 -03:00
266728fbf3 Algunas cosas de ShellCheck 2021-10-11 16:14:23 -03:00
78ed5db561 No usar echo -n (no es POSIX) 2021-10-11 16:13:38 -03:00
118d147835 Agregar Arreglando bugs ajenos al index 2021-10-11 16:12:48 -03:00
075782e988 Arreglando bugs ajenos 2021-10-11 16:12:42 -03:00
5c388d7c44 No dejar que colapsen los bloques de código 2021-10-11 16:10:55 -03:00
136b387a5f No dejar que colapsen los videos 2021-10-11 16:10:48 -03:00
1e62f49e5a Dar más espacio para los artículos 2021-10-11 16:10:35 -03:00
8bb3e76073 Permitir HTML en artículos 2021-10-11 16:10:22 -03:00
20734fcb66 No romperse con archivos con espacios en el nombre 2021-10-11 16:10:08 -03:00
9affac5109 Copiar videos .mp4 2021-10-11 16:09:41 -03:00
6 changed files with 237 additions and 26 deletions

201
Arreglando bugs ajenos.md Normal file
View file

@ -0,0 +1,201 @@
<small>2021/10/11</small>
Estoy aprendiendo alemán y mi principal recurso es el "Aprender Alemán" de la Deutsche Welle ([learngerman.dw.com](https://learngerman.dw.com/es/overview)). Sin embargo, en una de las recientes actualizaciones al sitio/app, rompieron _varias_ cosas.
Les mandé un mail al equipo de desarrollo ¡pero no me contestaron! Así que lo arreglé yo mismo.
Pero ¿cómo? El código es privativo y no tengo acceso. El _JavaScript_ que llega a mi navegador está minificado, es decir que se le elimina palabras y se comprime a un archivo para ahorrar en banda ancha. Pero **otra de las razones por las que se minifica es para no dar acceso al código.**
Sin embargo, el equipo de desarrollo cometió un error (¿intencionalmente?) en donde dejaron los "source maps". Los source maps son unos archivos que le permiten a las herramientas de desarrolladorx saber que parte del código minificado es cuál línea de código. ¡Por eso se llaman mapas! Para lograr esto, contienen casi todo el código del sitio.
Pero hay un último 5% del código que me hace falta para poder aplicar cambios: la configuración de las herramientas que minifican y compilan el código. Para mi suerte, este sitio utiliza una tecnología con la que ya tengo experiencia (React) así que puedo reconstruir esta configuración por mi cuenta.
Sabiendo esto, vayamos a lo práctico.
## Extrayendo el código
Empiezo por abrir la ventana de herramientas de desarrolladorx de mi navegador en el sitio y extraigo los enlaces a los archivos que terminan con `.map`, que son los source maps. Los guardo en un archivo con un enlace por línea y los descargo utilizando un script:
```sh
for f in $(cat files); do
wget $f
done
```
Ok, ahora necesito extraer los archivos de código de cada uno. Por suerte, ya existen herramientas que lo hagan por mi. Probé con [este script](https://gist.github.com/banyudu/b17a9cb3f05296b76a9f3051f66c3dcd) pero mi mejor experiencia fue con [este](https://github.com/akx/source-from-sourcemaps).
```sh
for f in *.map; do
node source-from-sourcemaps.js $f
done
```
## Levantando el código localmente
Después configuré una herramienta que compila código de React y hace otras magias por mi llamada [Vite](https://vitejs.dev). Podría haber usado la que lxs desarrolladorxs del sitio usaron originalmente, [webpack](https://webpack.js.org/), pero en mi experiencia es muy tedioso de configurar.
Tuve varios problemas al intentar levantar un entorno de desarrollo local con el código. Acá están algunos junto a sus soluciones en ningún orden particular:
- Vite esperaba que los archivos de React tengan la extensión `.jsx` mientras que originalmente tenían la extensión `.js`. Script:
```sh
for f in $(find -iname '*.js'); do
mv $f ${f}x
done
```
- Había una parte del código que eran archivos SVG "compilados" a React. Sin embargo, estos esperaban una variable especial de webpack (o algún plugin de webpack) que por supuesto no existía. Para esto, hice otro script para inyectarles esa variable:
```sh
for f in $(find -iname '*.svg.js'); do
echo 'const __webpack_public_path__ = "https://learngerman.dw.com/";' > ${f}.lol
cat $f >> ${f}.lol
mv ${f}.lol $f
done
```
- Tenía que instalar las dependencias de todo el proyecto. Esto lo hice con más script-fu:
```sh
grep -r "from '[\w@].*';" . > imports
sort -u imports > imports.uniq
xargs pnpm add < imports.uniq
# Por alguna razón esto no fue suficiente y tuve que manualmente añadir varias dependencias
pnpm add graphql videojs-seek-buttons videojs-contrib-quality-levels videojs-hls-quality-selector videojs-seek-buttons videojs-hls-quality-selector
```
- Faltaba tener el CSS localmente así que lo descargé:
```sh
for f in basestyles stylesheets customBaku; do
wget https://learngerman.dw.com/assets/css/${f}.css
done
```
- En `config.js` se tomaban variables de entorno que asumo existen en el entorno de trabajo de lxs desarrolladorxs. Yo las mentí:
```js
const process = {
env: {
// REACT_APP_GRAPHQL_BASE_URL: "https://learngerman.dw.com/graphql",
REACT_APP_GRAPHQL_BASE_URL: "https://localhost:4002/graphql",
REACT_APP_RECAPTCHA_SITEKEY: null,
},
};
```
Notese como originalmente había mentido diciendo que la URL de la API era learngerman.dw.com, pero luego lo cambié para que apunte a una URL local ya que la API no me permitía accederla desde un sitio no legítimo. Esa URL local apunta a un proxy a la API real.
Es muy probable que haya tenído que hacer más cosas y me haya olvidado. Fue mucho prueba y error hasta que el sitio finalmente cargó.
## Arreglando bug 1: problema de accesibilidad
Por un tiempo, tuve una de mis muñecas inaccesibles por unas semanas. Esto me obligo a usar exclusivamente la otra, complicando el uso del mouse y utilizando el teclado lo más posible.
Recientemente, en el sitio agregaron una solapa de "transcripción" mostrando todo el dialogo que había en el video del ejercicio. Sin embargo, cuando esta solapa estaba cerrada, se podían seguir seleccionando los enlaces dentro de la solapa con el teclado, haciendo la navegación por teclado tediosa.
<video controls src="Arreglando bugs ajenos.md-details.mp4"></video>
La solucion es simplemente usar el elemento de solapa que ya viene con el navegador: [`<details>`](https://developer.mozilla.org/es/docs/Web/HTML/Element/details). (La página de `<details>` en MDN esta desactualizada al momento de escribir este artículo.)
Estos fueron los cambios que hice:
```diff
diff --git a/./components/ContentContainer/AccordionContainer.jsx.orig b/./components/ContentContainer/AccordionContainer.jsx
index ed71204..d0ea66e 100644
--- a/./components/ContentContainer/AccordionContainer.jsx.orig
+++ b/./components/ContentContainer/AccordionContainer.jsx
@@ -6,43 +6,26 @@ import { colors } from '../../utils/css';
import { useTranslation } from '../../hooks/useTranslation';
export const AccordionContainer = ({ title, children, className }) => {
- const element = useRef(null);
- const [isOpen, { toggleOnClick }] = useToggle();
- const height = element.current ? element.current.scrollHeight : '0';
const titleTranslation = useTranslation(title);
return (
- <div className={className}>
- <div className="row noVMargins">
+ <details className={className}>
+ <summary className="row noVMargins">
<div className="col-sm-offset-1 col-sm-10 col-lg-offset-2 col-lg-8">
- <button tabIndex={0} onClick={toggleOnClick}>
<h4>
{titleTranslation}
- <ToggleableArrow
- className="toggleable-arrow"
- fill={colors.LG_BLACK}
- {...{
- isUp: isOpen,
- }}
- />
</h4>
- </button>
</div>
- </div>
+ </summary>
<AccordionContainerContent
- height={height}
- isOpen={isOpen}
- ref={element}
- aria-expanded={isOpen}
>
{children}
</AccordionContainerContent>
- </div>
+ </details>
);
};
export const AccordionContainerContent = styled.div`
- max-height: ${({ isOpen, height }) => (isOpen ? height : '1')}px;
overflow: hidden;
background-color: ${colors.LG_WHITE};
transition: max-height 0.7s;
```
## Arreglando bug 2: no cargan algunos ejercicios
Esto tardó mucho más tiempo de arreglar y sinceramente no vale la pena explicarlo. El cambio es bastante simple, lo explico en inglés:
```diff
diff --git a/components/Lesson/LessonExercise/LessonExerciseItem/LessonExerciseItem.jsx.orig b/components/Lesson/LessonExercise/LessonExerciseItem/LessonExerciseItem.jsx
index 6d35539..66b5005 100644
--- a/components/Lesson/LessonExercise/LessonExerciseItem/LessonExerciseItem.jsx.orig
+++ b/components/Lesson/LessonExercise/LessonExerciseItem/LessonExerciseItem.jsx
@@ -91,12 +91,20 @@ export const getExerciseMediaInputComponentByType = data => {
<MediaInputAudio data={data} />
</div>
);
+ // XXX: Here is the problem. These exercises return inputType == 'VIDEO'
+ // even though they don't have any videos (videos == []) causing some
+ // code that assumes that there is a video inside videos to fail
+ // (the MediaInputVideo component.)
case 'VIDEO':
- return (
- <div className="input-header-video">
- <MediaInputVideo data={data} />
- </div>
- );
+ // This "if" is our patch. If it isn't true, it fallsthrough to the default
+ // behaviour (returning null.)
+ if (data.content.videos.length > 0) {
+ return (
+ <div className="input-header-video">
+ <MediaInputVideo data={data} />
+ </div>
+ );
+ }
default:
return null;
}
```
## Conclusión
Más allá del desarrollo técnico que hice, creo que es más importante el político: [**el código desarrollado con dinero público debería ser público**](https://publiccode.eu/es/). Para el caso... todo el código debería ser público, pero eso es un debate para otro día.
Por otro lado, se me vienen a la mente la necesidad de testear el código para que no pasen cosas como bug 2, y también el testeo de herramientas de accesibilidad para bug 1.
Gute Nacht!

Binary file not shown.

View file

@ -1,2 +1,2 @@
- [Software Does Not Contain Errors](https://tuukkapensala.com/files/software_does_not_contain_errors.txt)
- [Semantic Compression](https://caseymuratori.com/blog_0015)
- [Software Does Not Contain Errors](https://tuukkapensala.com/files/software_does_not_contain_errors.txt)
- [Semantic Compression](https://caseymuratori.com/blog_0015)

View file

@ -1,42 +1,43 @@
#!/bin/sh
template () {
echo -n "<!doctype html>"
echo -n "<meta charset=utf-8>"
echo -n "<meta name=viewport content='width=device-width, initial-scale=1.0'>"
echo -n "<link rel=stylesheet href=drip.css>"
echo -n "<title>$1</title>"
echo "<!doctype html>"
echo "<meta charset=utf-8>"
echo "<meta name=viewport content='width=device-width, initial-scale=1.0'>"
echo "<link rel=stylesheet href=drip.css>"
echo "<title>$1</title>"
: "${inicio:=}"
if test "$inicio" != true; then
echo -n "<a href=.>☚ Volver al inicio</a>"
echo "<a href=.>☚ Volver al inicio</a>"
fi
if test -n "$2"; then
echo -n "<header>"
echo -n "<h1>$1</h1>"
echo -n "<p><small>Último cambio: <time datetime='$(git log -1 --format=%ai "$2")'>$(date -d "@$(git log -1 --format=%at "$2")" '+%Y-%m-%d %H:%M')</time></small></p>"
echo -n "</header>"
echo "<header>"
echo "<h1>$1</h1>"
echo "<p><small>Último cambio: <time datetime='$(git log -1 --format=%ai "$2")'>$(date -d "@$(git log -1 --format=%at "$2")" '+%Y-%m-%d %H:%M')</time></small></p>"
echo "</header>"
fi
}
outdir=build
mkdir -p $outdir
# Autocopiarnos :)
cp *.sh *.md *.css *.png "$outdir"
cp ./*.sh ./*.md ./*.css ./*.png ./*.mp4 "$outdir"
index="$outdir/index.html"
inicio=true header=false template "nulo.in" > "$index"
cmark --unsafe index.md >> "$index"
echo -n "<h2>Lista de páginas</h2><ul>" >> "$index"
echo "<h2>Lista de páginas</h2><ul>" >> "$index"
for file in *.md; do
test "$(basename $file)" = index.md && continue
test "$(basename "$file")" = index.md && continue
title="$(basename "$file" .md)"
outfile="$outdir/$title.html"
template "$title" "$file" > "$outfile"
cmark "$file" >> "$outfile"
cmark --unsafe "$file" >> "$outfile"
# TODO: hacky
sed -i "s/<a /<a rel='noopener noreferrer' /gi" "$outfile"
sed -i 's/\[\[\(.*\)\]\]/<a href="\1.html">\1<\/a>/g' "$outfile"
echo -n "<li><a href='$title.html'>$title</a></li>" >> "$index"
echo "<li><a href='$title.html'>$title</a></li>" >> "$index"
done
echo -n "</ul>" >> "$index"
echo "</ul>" >> "$index"

View file

@ -1,14 +1,19 @@
body {
font-family: sans-serif;
max-width: 30rem;
max-width: 45rem;
margin: 0 auto;
padding: 1rem;
}
img {
img,
video {
max-width: 100%;
}
abbr {
color: gray;
}
pre {
overflow-x: auto;
}

View file

@ -7,11 +7,15 @@ Este es mi hogar. ¿Estás perdidx?
Algunos de mis proyectos:
- [Manejador de Tareas](https://tareas.nulo.in)
- Laburos:
- [Salvá la costanera](https://salvalacostanera.com.ar), [código](https://gitea.nulo.in/Nulo/salva-la-costanera)
- Juguetes:
- [Cuarentena](https://cuarentena.nulo.in)
- [Este sitio](https://gitea.nulo.in/Nulo/sitio)
- [Manejador de Tareas](https://tareas.nulo.in)
- Laburos:
- [Salvá la costanera](https://salvalacostanera.com.ar), [código](https://gitea.nulo.in/Nulo/salva-la-costanera)
- Juguetes:
- [Cuarentena](https://cuarentena.nulo.in)
- [Este sitio](https://gitea.nulo.in/Nulo/sitio)
Algunas cosas que escribí recientemente:
- [[Arrelgando bugs ajenos]]
Webamigx: [nadie@nulo.in](mailto:nadie@nulo.in) <small>no gods no webmasters</small>