En pocas palabras
Una ficha de Ciencias y Matemáticas de dos páginas sobre el ciclo del agua, hecha diez veces. Las preguntas son las mismas; los números, las casillas, los renglones y la división se ven como los imprimen los libros de cada país.
Lo que vas a componer
La ficha 7 de un curso de Ciencias y Matemáticas de 4.º de Primaria, El agua, de viaje, en diez ediciones. Las preguntas son las mismas en todos los idiomas: elegir una respuesta, marcar verdadero o falso, completar con un banco de palabras, unir palabras con su significado, rodear una palabra, repartir el agua de un depósito y explicar por qué ahorrarla. Cada edición las imprime como lo hacen sus escuelas. Las fichas española y catalana ponen el número en un círculo, marcan V o F y dividen con el divisor en una caja a la derecha del dividendo. La francesa usa cuadrados, cases à cocher, huecos de puntos y papel Seyès para la respuesta. La alemana escribe R y F, Lückentext y 864 : 4 = en una línea, con la multiplicación en punto. La brasileña pide V o F entre paréntesis. La inglesa divide bajo la casita ⟌. La china numera sus secciones 一、二、, pone ( ) tras cada enunciado con A. B. C. en fila, pide √ o × y termina con 看拼音,写词语 en cuadros 田字格. La japonesa ofrece ア イ ウ y ○ ×, y la árabe va de derecha a izquierda con أ ب ج y صح o خطأ.
Esta receta responde a
- ¿Cómo compongo la misma ficha tal como los libros escolares de cada país componen sus ejercicios?
- ¿Cómo compongo la división larga tal como la escriben las escuelas de cada país?
- ¿Cómo compongo preguntas de examen chino: un paréntesis ( ) tras el enunciado y las opciones A. B. C. D. en una fila?
La respuesta corta
// The Markdown of every edition has the same seven exercises. What changes is this table:
// how the number prints, how options are labelled and answered, how true/false reads, where
// a blank is written, the paper of the open answer and the layout of long division.
const disc = { shape: 'disc' };
const square = { shape: 'square' };
const bare = { shape: 'none', suffix: '.' };
const TRADITIONS = {
es: { number: disc, options: { marker: 'none' }, trueFalse: { look: 'boxes' },
blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
fr: { number: square, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
blank: { look: 'dots' }, area: { kind: 'seyes', spacing: mm(8) },
arithmetic: { division: 'potence' } },
de: { number: square, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'inline' } },
it: { number: { shape: 'rounded' }, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
blank: { look: 'dots' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
pt: { number: bare, options: { marker: 'none' }, trueFalse: { look: 'bracket' },
blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
en: { number: bare, options: { marker: 'none' }, trueFalse: { look: 'boxes' },
blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'bracket' } },
// 一、二、 sections; ( ) after the stem and A. B. C. in a row; √ × in a bracket; 田字格.
zh: { number: { shape: 'none', format: 'simp-chinese-informal', suffix: '、' },
options: { labels: 'alpha-upper', suffix: '.', layout: 'row', bracket: true },
trueFalse: { look: 'bracket' }, blank: { look: 'line' },
area: { kind: 'tianzige', spacing: mm(13), lines: 1 }, arithmetic: { division: 'bracket' } },
// ア イ ウ in a row with ( ), ○ × in a bracket, the number in a square.
ja: { number: square, options: { labels: 'katakana', suffix: '', layout: 'row', bracket: true },
trueFalse: { look: 'bracket' }, blank: { look: 'line' }, area: { kind: 'lines' },
arithmetic: { division: 'bracket' } },
ar: { number: disc, options: { marker: 'none', prefix: '(', suffix: ')' },
trueFalse: { look: 'boxes' },
blank: { look: 'dots' }, area: { kind: 'lines' }, arithmetic: { division: 'bracket' } },
};
TRADITIONS.ca = TRADITIONS.es; // Catalan schools set exercises as Spanish ones do
Ingredientes
- Funciones
- Estilos de ejercicioOperaciones en columnaElección y verdadero o falsoEjerciciosHuecos y bancos de palabrasUnir y clasificarPreguntas abiertas y zonas de escrituraAperturas diseñadasAtributos de títuloPaleta de color semánticaFuentes chinas, japonesas y coreanasFuentes árabesLibros encuadernados por la derechaTexto de derecha a izquierdaSeparación silábica e idioma del documentoPáginas en un canvasExportación a PDF
- Tipografía
- Nunito, Baloo 2, Noto Serif SC, Noto Sans SC, Klee One, Noto Sans JP, Noto Naskh Arabic, Baloo Bhaijaan 2 (SIL OFL 1.1)
- Recursos
- Ninguno: todas las imágenes se dibujan en código
Elaboración
#1 · Pon cada tradición en una tabla
// The Markdown of every edition has the same seven exercises. What changes is this table:
// how the number prints, how options are labelled and answered, how true/false reads, where
// a blank is written, the paper of the open answer and the layout of long division.
const disc = { shape: 'disc' };
const square = { shape: 'square' };
const bare = { shape: 'none', suffix: '.' };
const TRADITIONS = {
es: { number: disc, options: { marker: 'none' }, trueFalse: { look: 'boxes' },
blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
fr: { number: square, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
blank: { look: 'dots' }, area: { kind: 'seyes', spacing: mm(8) },
arithmetic: { division: 'potence' } },
de: { number: square, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'inline' } },
it: { number: { shape: 'rounded' }, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
blank: { look: 'dots' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
pt: { number: bare, options: { marker: 'none' }, trueFalse: { look: 'bracket' },
blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
en: { number: bare, options: { marker: 'none' }, trueFalse: { look: 'boxes' },
blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'bracket' } },
// 一、二、 sections; ( ) after the stem and A. B. C. in a row; √ × in a bracket; 田字格.
zh: { number: { shape: 'none', format: 'simp-chinese-informal', suffix: '、' },
options: { labels: 'alpha-upper', suffix: '.', layout: 'row', bracket: true },
trueFalse: { look: 'bracket' }, blank: { look: 'line' },
area: { kind: 'tianzige', spacing: mm(13), lines: 1 }, arithmetic: { division: 'bracket' } },
// ア イ ウ in a row with ( ), ○ × in a bracket, the number in a square.
ja: { number: square, options: { labels: 'katakana', suffix: '', layout: 'row', bracket: true },
trueFalse: { look: 'bracket' }, blank: { look: 'line' }, area: { kind: 'lines' },
arithmetic: { division: 'bracket' } },
ar: { number: disc, options: { marker: 'none', prefix: '(', suffix: ')' },
trueFalse: { look: 'boxes' },
blank: { look: 'dots' }, area: { kind: 'lines' }, arithmetic: { division: 'bracket' } },
};
TRADITIONS.ca = TRADITIONS.es; // Catalan schools set exercises as Spanish ones do
Todas las ediciones tienen el mismo Markdown: siete vallas :::exercise con las respuestas en el texto (- [x], [[vapor]], - Evaporación -> El agua se convierte en vapor, - 864 : 4). Lo que cambia de un país a otro es la forma, así que vive en esta tabla y en ningún otro sitio: la figura y las cifras del número, las letras de las opciones y si el alumno marca una casilla o rodea una letra, el aspecto del verdadero o falso, el de los huecos, la zona de escritura y la colocación de la división. El catalán toma la fila del español tal cual.
#2 · Pon la tradición sobre el estilo de la casa
const T = TRADITIONS[LANG];
const ficha = {
id: 'ficha', ...T,
number: { background: col('accent'), color: T.number.shape === 'none' ? col('accent')
: col('paper'), fontFamily: LABEL, fontWeight: 700, ...T.number },
// Chinese and Japanese sheets set the instructions in the gothic (黑体, ゴシック).
instruction: { bold: true, color: col('ink'), ...(LANG === 'zh' || LANG === 'ja'
? { fontFamily: LABEL } : {}) },
blank: { color: col('ink'), weight: pt(0.7), ...T.blank },
match: { look: 'dots', gap: em(5), color: col('accent') },
bank: { order: 'alpha' },
area: { color: col('rule'), spacing: mm(9), weight: pt(0.6), ...T.area },
grid: { cell: mm(8.5), fontFamily: TEXT, rule: col('rule'), color: col('ink') },
marginTop: mm(7), marginBottom: mm(1), itemSpacing: em(0.4),
};
Un solo estilo de ejercicio, ficha, lleva lo que comparten las diez fichas (el azul de los números, los filetes grises, el aire entre ejercicios), y la fila de la edición se extiende sobre él. Lo que la fila no dice viene del idioma: T F, V F, R F, √ ×, ○ × y صح خطأ son palabras del propio motor, igual que a) b) c), A. B. C., ア イ ウ y أ ب ج, así que ninguna edición las escribe.
#3 · Da a cada escritura sus fuentes
const FACES = {
zh: { text: 'Noto Serif SC', label: 'Noto Sans SC' },
ja: { text: 'Klee One', label: 'Noto Sans JP' },
ar: { text: 'Noto Naskh Arabic', label: 'Baloo Bhaijaan 2' },
}[LANG] ?? { text: 'Nunito', label: 'Baloo 2' };
const [TEXT, LABEL] = [FACES.text, FACES.label];
Las ediciones latinas comparten Nunito y Baloo 2. La ficha china compone el texto en Song y los enunciados en Hei; la japonesa, el texto en Klee One, una letra de libro de texto, y los enunciados en una gótica; la árabe usa Noto Naskh Arabic. El corte más grueso de Klee One es el 600, así que la edición japonesa pone su negrita a 600 (boldFontWeight): un 700 lo dibujaría el navegador y la captura fallaría.
#4 · Encabeza la ficha con renglones para el nombre
const at = (to, edge, x = 0, y = 0, size) => ({ anchor: { to, edge },
offset: { x: mm(x), y: mm(y) }, ...(size && { size }) });
const field = (id, attr, x, width) => [
{ kind: 'text', id, content: `{attr.${attr}}`, fontFamily: LABEL, fontSize: pt(10),
fontWeight: 700, color: col('muted'), align: 'left', placement: at('container', 'top-left',
x, 28) },
{ kind: 'rule', id: `${id}-line`, direction: 'horizontal', thickness: pt(0.75),
color: col('rule'), placement: at('container', 'top-left', x + 16, 33, { width: mm(width) }) },
];
const head = { enabled: true, minHeight: mm(38), slot: { elements: [
{ kind: 'box', id: 'band', style: { backgroundColor: col('accent'), borderRadius: mm(3) },
placement: at('container', 'top-left', 0, 0, { width: 'fill', height: mm(21) }) },
{ kind: 'text', id: 'kicker', content: '{title} · {subtitle}', fontFamily: LABEL,
fontSize: pt(8.5), fontWeight: 700, color: col('tint'), align: 'left',
placement: at('container', 'top-left', 6, 3.5) },
{ kind: 'text', id: 'title', content: '{titleText}', fontFamily: LABEL, fontSize: pt(22),
fontWeight: 700, color: col('paper'), align: 'left', lineHeight: 1.1,
placement: at('container', 'top-left', 6, 9.5) },
...field('name', 'nombre', 0, 96), ...field('date', 'fecha', 120, 40),
] } };
El título de nivel 1 dibuja la banda, el curso tomado del frontmatter y el título, y dos campos con renglón cuyas palabras salen de los atributos del título (nombre="Nombre" fecha="Fecha"), así que la ficha alemana dice Datum y la japonesa 名前 sin una cadena en el código.
La receta completa
// ═══ Postext Cookbook · Nº 169 · One worksheet in ten school traditions ═════════
// https://postext.dev/en/cookbook/school-traditions-worksheet
// Code: MIT · Text: original (CC BY 4.0) · Pictures: none
// Fonts: Nunito, Baloo 2, Klee One, Noto Naskh Arabic and others (SIL OFL) · Needs postext ≥ 1.59.0
import {
buildDocument, withLoadedFonts, renderPageToCanvas,
} from 'https://esm.sh/postext';
import { renderToPdf, decompressWoff2 } from 'https://esm.sh/postext-pdf';
const LANG = 'es'; // @lang: the language of the worksheet (en es ca fr de it pt zh ja ar)
const RECIPE = 'school-traditions-worksheet';
// ─── 1 · Design ─────────────────────────────────────────────────────────────
// #region palette: a blue-black ink, one blue accent, a pale tint, grey rules
const palette = {
ink: '#1d2633', accent: '#2a5d9f', tint: '#e8f0fa', rule: '#a9b6c6', muted: '#5d6878',
paper: '#ffffff',
};
const col = (id) => ({ hex: palette[id], model: 'hex', paletteId: id });
const colorPalette = [
...Object.entries(palette).map(([id, hex]) => ({ id, name: id, value: { hex, model: 'hex' } })),
{ id: 'main-color', name: 'accent (defaults)', value: { hex: palette.accent, model: 'hex' } },
];
// #endregion
// #region faces: Latin editions share two faces; Chinese, Japanese and Arabic their own
const FACES = {
zh: { text: 'Noto Serif SC', label: 'Noto Sans SC' },
ja: { text: 'Klee One', label: 'Noto Sans JP' },
ar: { text: 'Noto Naskh Arabic', label: 'Baloo Bhaijaan 2' },
}[LANG] ?? { text: 'Nunito', label: 'Baloo 2' };
const [TEXT, LABEL] = [FACES.text, FACES.label];
// #endregion
// #region answer: the form of the exercises, as each country's school books set them
// The Markdown of every edition has the same seven exercises. What changes is this table:
// how the number prints, how options are labelled and answered, how true/false reads, where
// a blank is written, the paper of the open answer and the layout of long division.
const disc = { shape: 'disc' };
const square = { shape: 'square' };
const bare = { shape: 'none', suffix: '.' };
const TRADITIONS = {
es: { number: disc, options: { marker: 'none' }, trueFalse: { look: 'boxes' },
blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
fr: { number: square, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
blank: { look: 'dots' }, area: { kind: 'seyes', spacing: mm(8) },
arithmetic: { division: 'potence' } },
de: { number: square, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
El script.js compuesto funciona tal cual: pégalo como script de módulo en cualquier página o abre la receta en CodePen. Carpeta de la receta en GitHub ↗ (se abre en una nueva pestaña)
Variantes
#Imprime la copia del profesor
Cada respuesta va a su sitio en magenta: los paréntesis, las casillas, los huecos y el cociente.
exerciseStyles: [ficha],
+ exercises: { edition: 'teacher' },#Reúne las soluciones al pie de la ficha
placement: 'after' pone la clave de cada ejercicio debajo de él; 'inverted' la gira boca abajo, como en las páginas de pasatiempos.
+ exercises: { solutions: { placement: 'inverted', layout: 'key' } },Errores frecuentes
- Una fuente sin corte 700 hace sintética la negrita de los números de los enunciados. Da a esa fuente de texto un
boldFontWeightcon un peso que tenga. - El ○ de los enunciados japoneses y el √ de los chinos solo están en las fuentes CJK: ponlos en una frase del texto CJK, no en un rótulo latino.
Créditos
- Receta
- Ignacio Ferro
- Texto
- Texto original, CC BY 4.0
- Fuentes
- Nunito (SIL OFL 1.1) · Baloo 2 (SIL OFL 1.1) · Noto Serif SC (SIL OFL 1.1) · Noto Sans SC (SIL OFL 1.1) · Klee One (SIL OFL 1.1) · Noto Sans JP (SIL OFL 1.1) · Noto Naskh Arabic (SIL OFL 1.1) · Baloo Bhaijaan 2 (SIL OFL 1.1)
- Código
- MIT, como Postext
Editar este texto ↗ (se abre en una nueva pestaña)Carpeta de la receta en GitHub ↗ (se abre en una nueva pestaña)


