- Create latex template
- Create working generated and test document
- Use Noto Sans CJK JP font
- Create devshell
main
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

View File

@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1678972866,
"narHash": "sha256-YV8BcNWfNVgS449B6hFYFUg4kwVIQMNehZP+FNDs1LY=",
"lastModified": 1679139072,
"narHash": "sha256-Gtw2Yj8DfETie3u7iHv1y5Wt+plGRmp6nTQ0EEfaPho=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "cd34d6ed7ba7d5c4e44b04a53dc97edb52f2766c",
"rev": "08ef7dc8334521605a5c8b7086cc248e74ee338b",
"type": "github"
},
"original": {
@ -15,9 +15,22 @@
"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": {
"inputs": {
"nixpkgs": "nixpkgs",
"noto-cjk-jp-otf-regular": "noto-cjk-jp-otf-regular",
"yokutango": "yokutango"
}
},

View File

@ -1,25 +1,81 @@
{ inputs = {
nixpkgs.url = "nixpkgs/nixos-22.11";
yokutango = {
url = "git+https://git.nani.wtf/h7x4/yokutango?ref=master";
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";
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 {
devshells.default = {
inherit nativeBuildInputs FONTCONFIG_FILE;
};
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" {} ''
ln -s ${yokutango}/json $out
'';
yokutango2tex = pkgs.writers.writeHaskell "yokutango2tex" {
yokutango2tex = pkgs.writers.writeHaskellBin "yokutango2tex" {
libraries = with pkgs.haskellPackages; [ aeson bytestring ];
} (pkgs.lib.fileContents ./yokutango2tex.hs);
yokutango-pdf = pkgs.runCommand "yokutango-pdf" {} ''
${self.packages.${system}.yokutango2tex} ${self.packages.${system}.yokutango-json}
} (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;
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
View 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
View File

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

View File

@ -1,26 +1,35 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE NamedFieldPuns #-}
import Data.Aeson
import Data.String (fromString)
import GHC.Generics
import System.Directory
import System.Environment
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
data NorwegianWord = NorwegianWord { word :: String
, hints :: Maybe [String]
data NorwegianWord = NorwegianWord { word :: T.Text
, hints :: Maybe [T.Text]
} deriving (Generic, Show)
instance FromJSON NorwegianWord
instance ToJSON NorwegianWord where
toEncoding = genericToEncoding defaultOptions
data JapaneseWord = JapaneseWord { word :: String
, romaji :: Maybe String
, hints :: Maybe [String]
data JapaneseWord = JapaneseWord { word :: T.Text
, romaji :: Maybe T.Text
, hints :: Maybe [T.Text]
} deriving (Generic, Show)
instance FromJSON JapaneseWord
@ -31,18 +40,66 @@ data Card = Card { norwegian :: [NorwegianWord]
, japanese :: [JapaneseWord]
} deriving (Generic, Show)
data WordBlock = WordBlock { title :: T.Text
, cards :: [Card]
} deriving (Show)
instance FromJSON Card
instance ToJSON Card where
toEncoding = genericToEncoding defaultOptions
readJsonFile :: FilePath -> IO (Either String [Card])
readJsonFile path = eitherDecode <$> BS.readFile path
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 " "
. 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 = do
dir <- head <$> getArgs
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
-- Right cards -> mapM_ print cards
-- Left err -> putStr err