Misc:
- Create latex template - Create working generated and test document - Use Noto Sans CJK JP font - Create devshell
This commit is contained in:
parent
7d06b6304e
commit
9429ea82ad
19
flake.lock
generated
19
flake.lock
generated
@ -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"
|
||||
}
|
||||
},
|
||||
|
66
flake.nix
66
flake.nix
@ -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
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
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 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
|
||||
|
Loading…
Reference in New Issue
Block a user