Em poucas palavras
Um caderno escolar japonês: contas, quadradinhos, alternativas e certo ou errado numa página, kanji e leituras de cima para baixo na outra. Sob cada exercício vêm as respostas de cabeça para baixo; a criança vira o caderno para conferir.
O que você vai compor
Duas páginas de uma coleção de cadernos de atividades do 3.º ano, em formato B5. A página de contas corre na horizontal: uma faixa azul-clara com a etiqueta da matéria, o título e um tanuki como mascote, uma linha para o nome e um quadro para a nota, depois ひっ算 (contas armadas) com um quadradinho para cada algarismo do resultado, quadradinhos depois de seis contas, alternativas ア イ ウ em fila, afirmações ○× com um parêntese no fim da linha e dois problemas com linhas para escrever a conta. A página de kanji é composta como se imprime um caderno de 国語, de cima para baixo e da direita para a esquerda: leituras com um quadradinho para o kanji, palavras sublinhadas cuja leitura vai entre parênteses, alternativas para circular e um significado para escolher. Embaixo de cada exercício, as respostas vêm de cabeça para baixo em letra cinza pequena. A criança vê onde elas estão, não consegue lê-las de relance e vira o caderno para conferir.
Esta receita responde a
- Como imprimo as respostas de cabeça para baixo no pé de um exercício?
- Como componho uma página de exercícios japonesa em colunas verticais com o mesmo projeto da horizontal?
- Como componho a divisão longa do jeito que as escolas de cada país a escrevem?
A resposta curta
// `placement: 'inverted'` sets each exercise's key right after it in a box turned 180°: the
// pupil sees where the answers are without reading them, and turns the book to check. The
// key's words come from the exercise (the options' katakana, ○ and ×, the operations), so
// the Markdown holds nothing twice.
const drill = {
id: 'drill',
number: { shape: 'square', fontFamily: TEXT, fontWeight: 600, background: col('blue') },
instruction: { fontFamily: ROUND, bold: false },
options: { layout: 'row' }, // ア イ ウ side by side (the default labels in Japanese)
trueFalse: { look: 'bracket' }, // ( ) for ○ or ×
blank: { look: 'box', width: 'answer', color: col('rule') }, // □ to write in
area: { kind: 'lines', color: col('rule') },
grid: { rule: col('rule') },
solutions: { placement: 'inverted', box: 'kotae' },
marginTop: em(1.1), marginBottom: em(0.4),
};
const kotae = { id: 'kotae', title: '', backgroundEnabled: false, border: { enabled: false },
padding: { top: pt(0), right: pt(0), bottom: pt(0), left: pt(0) },
body: { fontFamily: ROUND, fontSize: pt(8), lineHeight: pt(12), color: col('muted'),
firstLineIndent: pt(0) },
marginTop: mm(1), marginBottom: mm(2), keepTogether: true };
Ingredientes
- Funcionalidades
- GabaritoEstilos de exercícioTexto verticalExercíciosContas armadasLacunas e bancos de palavrasEscolha e verdadeiro ou falsoPerguntas abertas e áreas de escritaKana, kanji e rōmajiFontes chinesas, japonesas e coreanasLinhas laterais (bōsen)Livros encadernados pela direitaChips no textoTrês ou mais colunasAberturas desenhadasAtributos de títuloImagens nos designs de páginaAncoragem de elementos de designPaleta de cores semânticaExportação para PDF
- Também usa
- Colunas num boxe ou no textoBoxes que se dividem ou ficam inteirosQuebra de linha em chinêsEquilíbrio de colunasEstilos de parágrafoFontes incorporadas ao PDFFiguras e tabelas como recursos
- Tipografia
- Klee One, Zen Maru Gothic (SIL OFL 1.1)
- Materiais
kitsune-600.jpgtanuki-600.jpg- A young tanuki in a yellow school hat holding a big pencil. (Generated With Diffusion Models, original)
- A fox cub in a red scarf reading a book. (Generated With Diffusion Models, original)
Preparo
#1 · Vire as respostas de cada exercício
O código está na resposta curta lá em cima. placement: 'inverted' põe as respostas depois de cada exercício num boxe girado 180°, e esse boxe fica dentro do boxe do próprio exercício, então uma quebra de página nunca separa os dois. As respostas saem do exercício: as operações com o resultado, o katakana da alternativa certa, ○ e ×, as palavras das lacunas. O estilo de boxe das respostas, kotae, só deixa a letra pequena e cinza.
#2 · Uma faixa para a página horizontal e para a vertical
// A heading design on a vertical page is laid along its column: x runs down the page and y
// to the left, so the same band stands at the right edge, from head to foot.
const BAND = 30; // mm: the band's depth (its height across, its width down)
const header = { enabled: true, minHeight: mm(BAND + 3), slot: { elements: [
{ kind: 'box', id: 'band', reserve: false, style: { backgroundColor: col('tint'),
borderRadius: mm(4) }, placement: { anchor: { to: 'container', edge: 'top-left' },
size: { width: 'fill', height: mm(BAND) } } },
{ kind: 'image', id: 'mascot', resourceId: '{attr.pic}', decorative: true, reserve: false,
placement: { anchor: { to: 'container', edge: 'top-right' }, offset: { x: mm(-4), y: mm(1) },
size: { width: mm(28), height: mm(28) } } },
{ kind: 'text', id: 'subject', content: '{attr.kicker}', fontFamily: ROUND, fontSize: pt(10),
fontWeight: 700, color: col('ink'), box: { backgroundColor: col('sun'), borderRadius: mm(3),
padding: { top: mm(0.6), bottom: mm(0.6), left: mm(2.4), right: mm(2.4) } },
placement: { anchor: { to: 'container', edge: 'top-left' }, offset: { x: mm(5), y: mm(5) } } },
{ kind: 'text', id: 'title', content: '{titleText}', fontFamily: ROUND, fontSize: pt(20),
fontWeight: 700, color: col('ink'),
placement: { anchor: { to: '#subject', edge: 'below' }, offset: { x: mm(0), y: mm(2.5) } } },
] } };
Numa página vertical, o design de um título se estende ao longo da sua coluna: o x desce pela página e o y avança para a esquerda. A faixa ancorada em top-left com a largura toda fica no alto da página de contas e ao longo da borda direita da página de kanji; o mascote ancorado em top-right fica na outra ponta da faixa nas duas. Nada no design nomeia uma direção.
#3 · Dois cadernos com um só texto
// Two drill books of one series: arithmetic across, bound on the left; kanji in columns,
// bound on the right (vertical text binds there by itself).
const [sansu, kokugo] = markdown.split(/(?=^# 春のことば)/m);
const build = (text) => withLoadedFonts(() => buildDocument({ markdown: text, resources },
config()), { ...kitFonts(FONTS), text: markdown });
const across = await build(sansu);
// 国語 is set in columns, top to bottom, right to left: the same design, turned.
writingMode = 'vertical-rl';
const docs = [across, await build(kokugo)];
A configuração é uma função, então cada composição recebe o seu próprio objeto, e entre uma e outra só muda writingMode. Na vertical, o caderno de 国語 se encaderna pela direita sozinho; showBook põe cada caderno do seu lado da lombada. O texto vai em Klee One, uma letra de livro didático, e as etiquetas em Zen Maru Gothic; as duas carregam a sua pontuação vertical para os parênteses da página de kanji.
A receita completa
// ═══ Postext Cookbook · Nº 172 · A Japanese drill with the answers upside down ═══
// https://postext.dev/en/cookbook/japanese-drill-upside-down-answers
// Code: MIT · Text: original (CC BY 4.0) · Pictures: generated with diffusion models
// Fonts: Klee One, Zen Maru Gothic (SIL OFL 1.1) · Needs postext ≥ 1.59.0
import {
buildDocument, withLoadedFonts, renderPageToCanvas, registerResourceImage,
loadVerticalAlternates,
} from 'https://esm.sh/postext';
import { renderToPdf, decompressWoff2 } from 'https://esm.sh/postext-pdf';
const LANG = 'ja'; // @lang: the language of the frame; the drill is Japanese in all
const RECIPE = 'japanese-drill-upside-down-answers';
// ─── 1 · Design ─────────────────────────────────────────────────────────────
// #region palette: a drill book's blue, a warm yellow and a pale sky for the band
const palette = {
ink: '#23272c', // text
blue: '#2a6cb0', // the accent: exercise numbers, the title band's rule, the score box
sun: '#f2c14e', // the subject badge
tint: '#eaf2fb', // the title band
rule: '#a8bfd8', // writing lines and boxes
muted: '#69717b', // folios, the name line, the upside-down answers
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.blue, model: 'hex' } },
];
// #endregion
// 教科書体 for the text a child copies from, a round gothic for the labels.
const [TEXT, ROUND] = ['Klee One', 'Zen Maru Gothic'];
// #region answer: the answers printed upside down under each exercise
// `placement: 'inverted'` sets each exercise's key right after it in a box turned 180°: the
// pupil sees where the answers are without reading them, and turns the book to check. The
// key's words come from the exercise (the options' katakana, ○ and ×, the operations), so
// the Markdown holds nothing twice.
const drill = {
id: 'drill',
number: { shape: 'square', fontFamily: TEXT, fontWeight: 600, background: col('blue') },
instruction: { fontFamily: ROUND, bold: false },
options: { layout: 'row' }, // ア イ ウ side by side (the default labels in Japanese)
trueFalse: { look: 'bracket' }, // ( ) for ○ or ×
blank: { look: 'box', width: 'answer', color: col('rule') }, // □ to write in
area: { kind: 'lines', color: col('rule') },
grid: { rule: col('rule') },
solutions: { placement: 'inverted', box: 'kotae' },
O script.js montado funciona como está: cole-o como script de módulo em qualquer página ou abra a receita no CodePen. Pasta da receita no GitHub ↗ (abre em uma nova aba)
Variações
#Junte as respostas no final
Um caderno com gabarito à parte deixa as respostas fora das páginas: chapterEnd as lista depois do último exercício.
- solutions: { placement: 'inverted', box: 'kotae' },
+ solutions: { placement: 'chapterEnd', box: 'kotae' },#Componha uma página de passatempos
A página de passatempos vira as respostas do mesmo jeito, em cartões de duas colunas.
Erros comuns
Erro comum
Fontes chinesas são carregadas em fatias, pelo bloco cjk
O Fontsource serve uma família chinesa, japonesa ou coreana em cerca de cem arquivos por peso, cada um com um intervalo de caracteres. loadFonts baixa só o arquivo latin, então na tela os caracteres chineses vêm de uma fonte do sistema e são medidos errado, e o fontsourceProvider entrega ao PDF esse arquivo latin, que os imprime como caixas vazias. Inclua o bloco cjk do kit, chame loadCjkFonts(FONTS, markdown) depois de loadFonts (uma vez por voz, com o texto que ela compõe, quando o livro usa várias fontes CJK) e passe a renderToPdf fontProvider: cjkPdfProvider: os dois pegam os arquivos que contêm os caracteres do texto. Fontes chinesas, japonesas e coreanas →
Erro comum
Marque um texto japonês como 'ja', nunca com zh-Hans nem LANG
As edições de uma receita são en e es, mas uma amostra japonesa é japonesa nas duas: `locale: LANG` a marcaria como inglês ou espanhol, e uma marcação chinesa a comporia pelas regras chinesas (pontuação Kaiming, kana pequeno livre para começar linha, 图 no lugar de 図, formas chinesas dos glifos no PDF). Desde o postext 1.30 a marcação é também o idioma em que o texto é composto (em que é medido, pintado e incorporado), então qualquer marcação que não seja 'ja' dá outras formas de glifo que não as japonesas (as chinesas, sob uma marcação chinesa) e outras quebras de linha. Escreva 'ja': isso escolhe a região do Japão (quebra de linha e pontuação da JLReq, pontos de ênfase em gergelim, espaçamento dos furigana, rótulos 図 e 表) e desativa a hifenização. O lint reprova um texto com kana sob uma marcação zh ou ko. Quebra de linha em japonês (kinsoku) →
- Uma leitura ainda não pode ficar sobre uma lacuna: um ruby dentro de
[[…]]faz parte da resposta escondida. O exercício de 漢字の書き取り põe cada leitura numa linha própria e o quadradinho depois dela, três por fileira num grupo:::columns; na página vertical, a leitura fica ao lado do quadradinho, como o furigana. - A Klee One só tem os pesos 400 e 600:
boldFontWeight: 600mantém todo negrito num corte que existe, inclusive os números dos itens e dos exercícios.
Créditos
- Receita
- Ignacio Ferro
- Texto
- Texto original, CC BY 4.0
- Imagens
- A young tanuki in a yellow school hat holding a big pencil. · Generated With Diffusion Models · original
- A fox cub in a red scarf reading a book. · Generated With Diffusion Models · original
- Fontes
- Klee One (SIL OFL 1.1) · Zen Maru Gothic (SIL OFL 1.1)
- Código
- MIT, como o Postext
Editar este texto ↗ (abre em uma nova aba)Pasta da receita no GitHub ↗ (abre em uma nova aba)


