- Create latex template
- Create working generated and test document
- Use Noto Sans CJK JP font
- Create devshell
This commit is contained in:
Oystein Kristoffer Tveit 2023-03-20 02:09:04 +01:00
parent 7d06b6304e
commit 9429ea82ad
Signed by: oysteikt
GPG Key ID: 9F2F7D8250F35146
5 changed files with 181 additions and 16 deletions

19
flake.lock generated

@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1678972866, "lastModified": 1679139072,
"narHash": "sha256-YV8BcNWfNVgS449B6hFYFUg4kwVIQMNehZP+FNDs1LY=", "narHash": "sha256-Gtw2Yj8DfETie3u7iHv1y5Wt+plGRmp6nTQ0EEfaPho=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "cd34d6ed7ba7d5c4e44b04a53dc97edb52f2766c", "rev": "08ef7dc8334521605a5c8b7086cc248e74ee338b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -15,9 +15,22 @@
"type": "indirect" "type": "indirect"
} }
}, },
"noto-cjk-jp-otf-regular": {
"flake": false,
"locked": {
"narHash": "sha256-o4SDCDPzhXj7A7qEslRiB5fbGtyqpy4fiVis7fnscN0=",
"type": "file",
"url": "https://github.com/notofonts/noto-cjk/raw/main/Sans/OTF/Japanese/NotoSansCJKjp-Regular.otf"
},
"original": {
"type": "file",
"url": "https://github.com/notofonts/noto-cjk/raw/main/Sans/OTF/Japanese/NotoSansCJKjp-Regular.otf"
}
},
"root": { "root": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"noto-cjk-jp-otf-regular": "noto-cjk-jp-otf-regular",
"yokutango": "yokutango" "yokutango": "yokutango"
} }
}, },

@ -1,25 +1,81 @@
{ inputs = { { inputs = {
nixpkgs.url = "nixpkgs/nixos-22.11"; nixpkgs.url = "nixpkgs/nixos-22.11";
yokutango = { yokutango = {
url = "git+https://git.nani.wtf/h7x4/yokutango?ref=master"; url = "git+https://git.nani.wtf/h7x4/yokutango?ref=master";
flake = false; flake = false;
}; };
noto-cjk-jp-otf-regular = {
url = "https://github.com/notofonts/noto-cjk/raw/main/Sans/OTF/Japanese/NotoSansCJKjp-Regular.otf";
flake = false;
};
}; };
outputs = { self, nixpkgs, yokutango }: let outputs = { self, nixpkgs, yokutango, noto-cjk-jp-otf-regular }: let
system = "x86_64-linux"; system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
inherit (pkgs) lib;
nativeBuildInputs = with pkgs; [
self.packages.${system}.yokutango2tex
texlive.combined.scheme-full
];
FONTCONFIG_FILE = pkgs.makeFontsConf {
fontDirectories = with pkgs; [
noto-fonts
self.packages.${system}.noto-sans-cjk-jp
];
};
in { in {
devshells.default = {
inherit nativeBuildInputs FONTCONFIG_FILE;
};
packages.${system} = { packages.${system} = {
default = self.packages.${system}.yokutango-pdf;
noto-sans-cjk-jp = pkgs.runCommandLocal "noto-sans-cjk-jp" {} ''
mkdir -p $out/share/fonts/opentype/noto-cjk
ln -s ${noto-cjk-jp-otf-regular} $out/share/fonts/opentype/noto-cjk/NotoSansCJKjp-Regular.otf
'';
yokutango-json = pkgs.runCommandLocal "yokutango-json" {} '' yokutango-json = pkgs.runCommandLocal "yokutango-json" {} ''
ln -s ${yokutango}/json $out ln -s ${yokutango}/json $out
''; '';
yokutango2tex = pkgs.writers.writeHaskell "yokutango2tex" {
yokutango2tex = pkgs.writers.writeHaskellBin "yokutango2tex" {
libraries = with pkgs.haskellPackages; [ aeson bytestring ]; libraries = with pkgs.haskellPackages; [ aeson bytestring ];
} (pkgs.lib.fileContents ./yokutango2tex.hs); } (lib.fileContents ./yokutango2tex.hs);
yokutango-pdf = pkgs.runCommand "yokutango-pdf" {} ''
${self.packages.${system}.yokutango2tex} ${self.packages.${system}.yokutango-json} 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;
combined = pkgs.writeText ''yokutango-test.tex'' (builtins.replaceStrings ["% --- %"] [body] template);
in pkgs.runCommand "yokutango-pdf" { inherit nativeBuildInputs FONTCONFIG_FILE; } ''
mkdir $out
ln -s ${combined} yokutango-test.tex
ln -s ${combined} $out/yokutango-test.tex
xelatex yokutango-test.tex
mv yokutango-test.pdf $out
'';
}; };
}; };
} }

29
template.tex Normal file

@ -0,0 +1,29 @@
\documentclass{article}
\usepackage{fontspec}
\usepackage{xeCJK}
\usepackage{ruby}
\usepackage{longtable}
\usepackage{parskip}
\usepackage{booktabs}
\usepackage[portrait,paper=a4paper,total={6in,8in}]{geometry}
\usepackage[dvipsnames, table]{xcolor}
\definecolor{rowColor}{RGB}{64, 120, 20}
\setmainfont{Noto Sans}
\setCJKmainfont{Noto Sans CJK JP}
\rowcolors{1}{}{rowColor!30!white}
\setlength{\parindent}{0pt}
\setlength{\parskip}{\baselineskip}
\renewcommand{\rubysep}{1mm}
\begin{document}
% --- %
\end{document}

10
testContent.tex Normal file

@ -0,0 +1,10 @@
\def\arraystretch{1.5}
\begin{longtable}[]{@{}ll@{}}
\toprule
日本語 & Norsk \\
\midrule
\endhead
\ruby{言葉}{ことば} & ord \\
\ruby{}{ぶん} & setning \\
\bottomrule
\end{longtable}

@ -1,26 +1,35 @@
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE NamedFieldPuns #-}
import Data.Aeson import Data.Aeson
import Data.String (fromString)
import GHC.Generics import GHC.Generics
import System.Directory import System.Directory
import System.Environment import System.Environment
import System.FilePath import System.FilePath
import Data.Maybe
import Data.List (intersperse)
import qualified Data.Text.Lazy as T
import qualified Data.Text.Lazy.IO as T
import qualified Data.Text.Lazy.Encoding as T
import qualified Data.ByteString.Lazy as BS import qualified Data.ByteString.Lazy as BS
data NorwegianWord = NorwegianWord { word :: String data NorwegianWord = NorwegianWord { word :: T.Text
, hints :: Maybe [String] , hints :: Maybe [T.Text]
} deriving (Generic, Show) } deriving (Generic, Show)
instance FromJSON NorwegianWord instance FromJSON NorwegianWord
instance ToJSON NorwegianWord where instance ToJSON NorwegianWord where
toEncoding = genericToEncoding defaultOptions toEncoding = genericToEncoding defaultOptions
data JapaneseWord = JapaneseWord { word :: String data JapaneseWord = JapaneseWord { word :: T.Text
, romaji :: Maybe String , romaji :: Maybe T.Text
, hints :: Maybe [String] , hints :: Maybe [T.Text]
} deriving (Generic, Show) } deriving (Generic, Show)
instance FromJSON JapaneseWord instance FromJSON JapaneseWord
@ -31,18 +40,66 @@ data Card = Card { norwegian :: [NorwegianWord]
, japanese :: [JapaneseWord] , japanese :: [JapaneseWord]
} deriving (Generic, Show) } deriving (Generic, Show)
data WordBlock = WordBlock { title :: T.Text
, cards :: [Card]
} deriving (Show)
instance FromJSON Card instance FromJSON Card
instance ToJSON Card where instance ToJSON Card where
toEncoding = genericToEncoding defaultOptions toEncoding = genericToEncoding defaultOptions
readJsonFile :: FilePath -> IO (Either String [Card]) readJsonFile :: FilePath -> IO (Either String WordBlock)
readJsonFile path = eitherDecode <$> BS.readFile path readJsonFile path = do
fileContent <- BS.readFile path
return $ cardsToWordblock <$> eitherDecode fileContent
where
formatPath :: FilePath -> T.Text
formatPath = T.append " "
. fromMaybe "???"
. T.stripPrefix "yokutango_"
. fromString
. takeBaseName
cardsToWordblock cards = WordBlock { title = formatPath path
, cards = cards
}
cardToRow :: Card -> T.Text
cardToRow card = mconcat [ japanesePart card, " $\\longleftrightarrow$ ", norwegianPart card ]
where
jpWordToText :: JapaneseWord -> T.Text
jpWordToText JapaneseWord { word, romaji, hints } =
case (word, romaji, hints) of
(w, Just r, _) -> mconcat [ "\\ruby{", w, "}{", r, "}" ]
(w, Nothing, _) -> w
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
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"]
main :: IO () main :: IO ()
main = do main = do
dir <- head <$> getArgs dir <- head <$> getArgs
filePaths <- map (\x -> joinPath [dir, x]) <$> listDirectory dir filePaths <- map (\x -> joinPath [dir, x]) <$> listDirectory dir
jsonFiles <- mapM readJsonFile filePaths 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 -- case jsonFiles of
-- Right cards -> mapM_ print cards -- Right cards -> mapM_ print cards
-- Left err -> putStr err -- Left err -> putStr err