Generate booklets
This commit is contained in:
parent
9429ea82ad
commit
7b7eb07cd8
15
2page-booklet-wrapper.tex
Normal file
15
2page-booklet-wrapper.tex
Normal file
@ -0,0 +1,15 @@
|
||||
\documentclass[a4paper]{article}
|
||||
|
||||
\usepackage[final]{pdfpages}
|
||||
|
||||
\newcommand*{\numberofpages}[1]{%
|
||||
\the\XeTeXpdfpagecount"#1" %
|
||||
}
|
||||
|
||||
\newcounter{numberofsignaturepages}%
|
||||
|
||||
\begin{document}
|
||||
\setcounter{numberofsignaturepages}{\numberofpages{yokutango.pdf}}%
|
||||
\addtocounter{numberofsignaturepages}{4}%
|
||||
\includepdf[pages=-,nup=1x2,landscape,signature=\thenumberofsignaturepages]{yokutango.pdf}
|
||||
\end{document}
|
54
flake.nix
54
flake.nix
@ -28,13 +28,37 @@
|
||||
self.packages.${system}.noto-sans-cjk-jp
|
||||
];
|
||||
};
|
||||
|
||||
mkYokutango-pdf = { paper ? "a4paper" }: let
|
||||
template = lib.fileContents ./template.tex;
|
||||
y2t-output-d = pkgs.runCommand "yokutango2tex-output" {} ''
|
||||
${self.packages.${system}.yokutango2tex}/bin/yokutango2tex ${self.packages.${system}.yokutango-json} > $out
|
||||
'';
|
||||
y2t-output = lib.fileContents y2t-output-d;
|
||||
combined = pkgs.writeText ''yokutango.tex'' (builtins.replaceStrings [
|
||||
"% --- %"
|
||||
"$paper$"
|
||||
] [
|
||||
y2t-output
|
||||
paper
|
||||
] template);
|
||||
in pkgs.runCommand "yokutango-pdf" { inherit nativeBuildInputs FONTCONFIG_FILE; } ''
|
||||
mkdir $out
|
||||
ln -s ${combined} yokutango.tex
|
||||
ln -s ${combined} $out/yokutango.tex
|
||||
xelatex yokutango.tex
|
||||
xelatex yokutango.tex
|
||||
ln -s ${./2page-booklet-wrapper.tex} yokutango-book.tex
|
||||
xelatex yokutango-book.tex
|
||||
mv yokutango.pdf yokutango-book.pdf $out
|
||||
'';
|
||||
in {
|
||||
devshells.default = {
|
||||
devShells.${system}.default = pkgs.mkShell {
|
||||
inherit nativeBuildInputs FONTCONFIG_FILE;
|
||||
};
|
||||
|
||||
packages.${system} = {
|
||||
default = self.packages.${system}.yokutango-pdf;
|
||||
default = self.packages.${system}.yokutango-pdf-a5;
|
||||
|
||||
noto-sans-cjk-jp = pkgs.runCommandLocal "noto-sans-cjk-jp" {} ''
|
||||
mkdir -p $out/share/fonts/opentype/noto-cjk
|
||||
@ -45,25 +69,6 @@
|
||||
ln -s ${yokutango}/json $out
|
||||
'';
|
||||
|
||||
yokutango2tex = pkgs.writers.writeHaskellBin "yokutango2tex" {
|
||||
libraries = with pkgs.haskellPackages; [ aeson bytestring ];
|
||||
} (lib.fileContents ./yokutango2tex.hs);
|
||||
|
||||
yokutango-pdf = let
|
||||
template = lib.fileContents ./template.tex;
|
||||
y2t-output-d = pkgs.runCommand "yokutango2tex-output" {} ''
|
||||
${self.packages.${system}.yokutango2tex}/bin/yokutango2tex ${self.packages.${system}.yokutango-json} > $out
|
||||
'';
|
||||
y2t-output = lib.fileContents y2t-output-d;
|
||||
combined = pkgs.writeText ''yokutango.tex'' (builtins.replaceStrings ["% --- %"] [y2t-output] template);
|
||||
in pkgs.runCommand "yokutango-pdf" { inherit nativeBuildInputs FONTCONFIG_FILE; } ''
|
||||
mkdir $out
|
||||
ln -s ${combined} yokutango.tex
|
||||
ln -s ${combined} $out/yokutango.tex
|
||||
xelatex yokutango.tex
|
||||
mv yokutango.pdf $out
|
||||
'';
|
||||
|
||||
yokutango-test = let
|
||||
template = lib.fileContents ./template.tex;
|
||||
body = lib.fileContents ./testContent.tex;
|
||||
@ -73,9 +78,16 @@
|
||||
ln -s ${combined} yokutango-test.tex
|
||||
ln -s ${combined} $out/yokutango-test.tex
|
||||
xelatex yokutango-test.tex
|
||||
xelatex yokutango-test.tex
|
||||
mv yokutango-test.pdf $out
|
||||
'';
|
||||
|
||||
yokutango2tex = pkgs.writers.writeHaskellBin "yokutango2tex" {
|
||||
libraries = with pkgs.haskellPackages; [ aeson bytestring ];
|
||||
} (lib.fileContents ./yokutango2tex.hs);
|
||||
|
||||
yokutango-pdf-a5 = mkYokutango-pdf { paper = "a5paper"; };
|
||||
yokutango-pdf-a4 = mkYokutango-pdf { paper = "a4paper"; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
44
template.tex
44
template.tex
@ -2,28 +2,58 @@
|
||||
|
||||
\usepackage{fontspec}
|
||||
\usepackage{xeCJK}
|
||||
\usepackage{ruby}
|
||||
\usepackage{longtable}
|
||||
\usepackage{parskip}
|
||||
\usepackage{booktabs}
|
||||
|
||||
\usepackage[portrait,paper=a4paper,total={6in,8in}]{geometry}
|
||||
|
||||
\usepackage[twoside,paper=$paper$]{geometry}
|
||||
\usepackage[dvipsnames, table]{xcolor}
|
||||
\definecolor{rowColor}{RGB}{64, 120, 20}
|
||||
\usepackage{mathtools}
|
||||
\usepackage{multicol}
|
||||
|
||||
\setmainfont{Noto Sans}
|
||||
\setCJKmainfont{Noto Sans CJK JP}
|
||||
|
||||
\definecolor{rowColor}{RGB}{149, 184, 230}
|
||||
\definecolor{headerColor}{gray}{1}
|
||||
\rowcolors{1}{}{rowColor!30!white}
|
||||
|
||||
\setlength{\parindent}{0pt}
|
||||
\setlength{\parskip}{\baselineskip}
|
||||
|
||||
\renewcommand{\rubysep}{1mm}
|
||||
\setlength{\columnsep}{1.5cm}
|
||||
\setlength{\columnseprule}{0.2pt}
|
||||
|
||||
\setcounter{secnumdepth}{0}
|
||||
|
||||
\newcommand{\ruby}[2]{$\stackrel{\text{#2}}{\text{#1}}$}
|
||||
|
||||
\renewcommand\arraystretch{1.5}
|
||||
\setlength\extrarowheight{5pt}
|
||||
\begin{document}
|
||||
|
||||
\thispagestyle{empty}
|
||||
|
||||
\topskip0pt
|
||||
\vspace*{\fill}
|
||||
\begin{center}
|
||||
{
|
||||
\fontsize{30pt}{36pt}\normalfont
|
||||
よく単語
|
||||
}
|
||||
|
||||
\vspace*{1cm}
|
||||
|
||||
March 2023
|
||||
\end{center}
|
||||
\vspace*{\fill}
|
||||
|
||||
\newpage
|
||||
|
||||
\begin{multicols}{2}
|
||||
\tableofcontents
|
||||
\end{multicols}
|
||||
|
||||
\newpage
|
||||
|
||||
% --- %
|
||||
|
||||
\end{document}
|
||||
|
@ -1,10 +1,17 @@
|
||||
\def\arraystretch{1.5}
|
||||
\begin{longtable}[]{@{}ll@{}}
|
||||
\toprule
|
||||
日本語 & Norsk \\
|
||||
\midrule
|
||||
\endhead
|
||||
\ruby{言葉}{ことば} & ord \\
|
||||
\ruby{文}{ぶん} & setning \\
|
||||
\bottomrule
|
||||
\setlength\extrarowheight{5pt}
|
||||
\begin{longtable}[]{|l|c@{}|l@{}|l|}
|
||||
Status & 日本語 & Norsk & Notes \\
|
||||
\endhead
|
||||
& \ruby{統合失調症}{とうごうしっちょうしょう} & schizofrenia & \\
|
||||
& \ruby{点火する}{てんかする} & å sette fyr & \\
|
||||
& \ruby{石英}{せきえい} & kvarts & \\
|
||||
& \ruby{房}{ふさ} & en bunke & \\
|
||||
& \ruby{新来者}{しんらいしゃ} & nykommer & \\
|
||||
& \ruby{伝わる}{つたわる} & å sende (et signal) & \\
|
||||
& \ruby{伝わる}{つたわる} & å sende $\begin{cases} \text{et signal} \\ \text{en melding} \\ \text{bølger} \\ \text{to transmit} \end{cases}$ & \\
|
||||
& \ruby{伝わる}{つたわる} & \begin{tabular}{l@{}}
|
||||
å sende (et signal) \\
|
||||
å sende $\begin{pmatrix} \text{et signal} \\ \text{en melding} \\ \text{bølger} \\ \text{to transmit} \end{pmatrix}$ \\
|
||||
\end{tabular} & \\
|
||||
\end{longtable}
|
||||
|
106
yokutango2tex.hs
106
yokutango2tex.hs
@ -2,7 +2,6 @@
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE RecordWildCards #-}
|
||||
{-# LANGUAGE NamedFieldPuns #-}
|
||||
|
||||
import Data.Aeson
|
||||
@ -12,7 +11,8 @@ import System.Directory
|
||||
import System.Environment
|
||||
import System.FilePath
|
||||
import Data.Maybe
|
||||
import Data.List (intersperse)
|
||||
import Data.List (intersperse, sort)
|
||||
import Control.Applicative ((<|>))
|
||||
|
||||
import qualified Data.Text.Lazy as T
|
||||
import qualified Data.Text.Lazy.IO as T
|
||||
@ -48,13 +48,33 @@ instance FromJSON Card
|
||||
instance ToJSON Card where
|
||||
toEncoding = genericToEncoding defaultOptions
|
||||
|
||||
data LaTeXRow = LaTeXRow { jw :: T.Text
|
||||
, nw :: T.Text
|
||||
}
|
||||
|
||||
(+?) :: Semigroup a => a -> Maybe a -> a
|
||||
a +? b = case b of
|
||||
Nothing -> a
|
||||
Just b' -> a <> b'
|
||||
|
||||
flipAppend :: T.Text -> T.Text -> T.Text
|
||||
flipAppend = flip T.append
|
||||
|
||||
wrap :: T.Text -> T.Text -> T.Text -> T.Text
|
||||
wrap s e w = mconcat [s, w, e]
|
||||
|
||||
indent :: T.Text -> T.Text
|
||||
indent = mconcat
|
||||
. map (wrap "\t" "\n")
|
||||
. T.splitOn "\n"
|
||||
|
||||
readJsonFile :: FilePath -> IO (Either String WordBlock)
|
||||
readJsonFile path = do
|
||||
fileContent <- BS.readFile path
|
||||
return $ cardsToWordblock <$> eitherDecode fileContent
|
||||
where
|
||||
formatPath :: FilePath -> T.Text
|
||||
formatPath = T.append " "
|
||||
formatPath = T.append "単語 "
|
||||
. fromMaybe "???"
|
||||
. T.stripPrefix "yokutango_"
|
||||
. fromString
|
||||
@ -64,42 +84,84 @@ readJsonFile path = do
|
||||
, cards = cards
|
||||
}
|
||||
|
||||
|
||||
cardToRow :: Card -> T.Text
|
||||
cardToRow card = mconcat [ japanesePart card, " $\\longleftrightarrow$ ", norwegianPart card ]
|
||||
cardToRow :: Card -> LaTeXRow
|
||||
cardToRow card = LaTeXRow { jw = japanesePart card
|
||||
, nw = norwegianPart card
|
||||
}
|
||||
where
|
||||
ruby :: T.Text -> T.Text -> T.Text
|
||||
ruby main top = mconcat [ "\\ruby{", main, "}{", top, "}" ]
|
||||
|
||||
subtable :: [T.Text] -> T.Text
|
||||
subtable rows = mconcat [ "\\begin{tabular}{@{}l@{}}\n"
|
||||
, mconcat $ map (\t -> mconcat ["\t", t, " \\\\\n"]) rows
|
||||
, "\\end{tabular}"
|
||||
]
|
||||
|
||||
hintsToPmatrix :: [T.Text] -> T.Text
|
||||
hintsToPmatrix = wrap " $\\begin{pmatrix}" "\\end{pmatrix}$"
|
||||
. mconcat
|
||||
. intersperse " \\\\ "
|
||||
. map (wrap "\\text{" "}")
|
||||
|
||||
jpWordToText :: JapaneseWord -> T.Text
|
||||
jpWordToText JapaneseWord { word, romaji, hints } =
|
||||
case (word, romaji, hints) of
|
||||
(w, Just r, _) -> mconcat [ "\\ruby{", w, "}{", r, "}" ]
|
||||
(w, Nothing, _) -> w
|
||||
jpWordToText JapaneseWord { word, romaji, hints } =
|
||||
case hints of
|
||||
Nothing -> furiganaBlock
|
||||
(Just [hint]) -> mconcat [ furiganaBlock, " (", hint, ")" ]
|
||||
(Just hints) -> subtable [mconcat [furiganaBlock, hintsToPmatrix hints ]]
|
||||
where
|
||||
rubyStr = ruby word <$> romaji
|
||||
furiganaBlock = fromMaybe word rubyStr
|
||||
|
||||
noWordToText :: NorwegianWord -> T.Text
|
||||
noWordToText NorwegianWord { word, hints } = word
|
||||
|
||||
japanesePart (Card { japanese }) = mconcat $ intersperse ("\\\\\n" :: T.Text) $ map jpWordToText japanese
|
||||
norwegianPart (Card { norwegian }) = mconcat $ intersperse ("\\\\\n" :: T.Text) $ map noWordToText norwegian
|
||||
|
||||
noWordToText NorwegianWord { word, hints } =
|
||||
case hints of
|
||||
Nothing -> word
|
||||
Just [hint] -> mconcat [word, " (", hint, ")"]
|
||||
Just hints -> subtable [mconcat [ word, hintsToPmatrix hints]]
|
||||
|
||||
japanesePart :: Card -> T.Text
|
||||
japanesePart (Card { japanese = [jpWord] }) = jpWordToText jpWord
|
||||
japanesePart (Card { japanese }) = subtable $ map jpWordToText japanese
|
||||
|
||||
norwegianPart :: Card -> T.Text
|
||||
norwegianPart (Card { norwegian = [noWord] }) = noWordToText noWord
|
||||
norwegianPart (Card { norwegian }) = subtable $ map noWordToText norwegian
|
||||
|
||||
wordblockToTable :: WordBlock -> T.Text
|
||||
wordblockToTable block = mconcat tablePieces
|
||||
where
|
||||
rows = map ((\t -> T.append t "\\\\\n") . cardToRow) (cards block)
|
||||
tablePieces = [ "\\section*{", title block, "}\n" ] ++ rows ++ ["\\newpage"]
|
||||
rows :: [LaTeXRow]
|
||||
rows = map cardToRow (cards block)
|
||||
|
||||
rowToText :: LaTeXRow -> T.Text
|
||||
rowToText (LaTeXRow { jw, nw }) = indent $ mconcat [ " & ", jw, " & ", nw, " & \\\\\n" ]
|
||||
|
||||
tablePieces :: [T.Text]
|
||||
tablePieces = [ "\\section{", title block, "}\n"
|
||||
, "\\begin{longtable}{|l|l@{}|l@{}|l|}\n"
|
||||
, "\\hline\n"
|
||||
, "\\rowcolor{headerColor}\n"
|
||||
, "Status & 日本語 & Norsk & Extra Notes \\\\\n"
|
||||
, "\\hline\n"
|
||||
, "\\endhead\n"
|
||||
, "\\hline"
|
||||
, "\\endfoot"
|
||||
]
|
||||
++ map rowToText rows
|
||||
++ [ "\\end{longtable}\n"
|
||||
, "\\newpage\n\n"
|
||||
]
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
dir <- head <$> getArgs
|
||||
filePaths <- map (\x -> joinPath [dir, x]) <$> listDirectory dir
|
||||
filePaths <- sort . map (\x -> joinPath [dir, x]) <$> listDirectory dir
|
||||
wordBlocks :: Either str [WordBlock] <- sequence <$> mapM readJsonFile filePaths
|
||||
|
||||
let output = case wordBlocks of
|
||||
Right blocks -> mconcat $ map wordblockToTable blocks
|
||||
Left err -> fromString err
|
||||
|
||||
BS.putStr $ T.encodeUtf8 $ output
|
||||
-- case jsonFiles of
|
||||
-- Right cards -> mapM_ print cards
|
||||
-- Left err -> putStr err
|
||||
BS.putStr $ T.encodeUtf8 output
|
||||
|
Loading…
Reference in New Issue
Block a user