From 0a2d3b631f3d3e6d042e02b9a6598df415f8f10d Mon Sep 17 00:00:00 2001 From: Julien Moutinho Date: Thu, 19 Jun 2025 05:35:08 +0200 Subject: [PATCH] update --- .gitignore | 1 + data/.gitignore | 4 + data/styles/rosetta.css | 11 +- flake.nix | 4 +- src/Wiktionary.hs | 161 ++++++++++++++++++ src/Worksheets/Writing/Rosetta.hs | 58 ++----- tests/Spec.hs | 14 +- tests/Worksheets/Writing/RosettaSpec.hs | 86 ++++++++-- .../Writing/RosettaSpec/Fraise/rosetta.html | 104 +++++------ .../Writing/RosettaSpec/ponies/rosetta.html | 102 +++++------ .../RosettaSpec/poniesRaces1/rosetta.html | 100 +++++------ .../RosettaSpec/poniesRaces2/rosetta.html | 100 +++++------ .../poup\303\251eArielle/rosetta.html" | 100 +++++------ .../poup\303\251eBella/rosetta.html" | 98 +++++------ worksheets.cabal | 14 +- 15 files changed, 587 insertions(+), 370 deletions(-) create mode 100644 src/Wiktionary.hs diff --git a/.gitignore b/.gitignore index fac2474..45e5bd2 100644 --- a/.gitignore +++ b/.gitignore @@ -16,5 +16,6 @@ dist-newstyle/ dist/ dump-core/ hlint.html +libs/ old/ result* diff --git a/data/.gitignore b/data/.gitignore index 7aa981d..98b3f6c 100644 --- a/data/.gitignore +++ b/data/.gitignore @@ -1,3 +1,7 @@ *.avif *.jpg +*.jsonl +*.sqlite +*.ttl *.webp +langs diff --git a/data/styles/rosetta.css b/data/styles/rosetta.css index 9c1ef59..00ca006 100644 --- a/data/styles/rosetta.css +++ b/data/styles/rosetta.css @@ -26,6 +26,8 @@ body { .page-PageSizeA4-PageOrientationPortrait { height:297mm; width:210mm; + /* ExplanationNote: to bind the paper for easy writing. */ + margin-top:1cm; } .page-PageSizeA4-PageOrientationLandscape { height:210mm; @@ -53,7 +55,7 @@ body { /* ExplanationNote: even when printing with the option "Shrink to Print Area" * pixels too close to the border can get cropped. */ - padding:1.5mm; + padding:2mm; display:grid; column-gap:5mm; row-gap:1mm; @@ -81,6 +83,8 @@ body { display:block; border:0; width:100%; + height:100%; + object-fit:contain; object-position:right center; overflow:hidden; } @@ -119,10 +123,13 @@ body { display:grid; gap:1px; background-color:#aaa; - overflow: hidden; /* ExplanationNote: avoid rounded borders to be cropped by background-color: */ + /* ExplanationNote: avoid rounded borders to be cropped by background-color: */ + overflow: hidden; border:1px solid #aaa; + /* border-top-left-radius:3mm; border-top-right-radius:3mm; + */ } .writing-words-word:last-child { margin-right:0; diff --git a/flake.nix b/flake.nix index 9c0c63a..02a7cfe 100644 --- a/flake.nix +++ b/flake.nix @@ -35,14 +35,16 @@ #pkgs = import inputs.nixpkgs { inherit system; }; pkgs = inputs.nixpkgs.legacyPackages.${system}; haskellPackages = pkgs.haskellPackages.extend (with pkgs.haskell.lib; finalHaskellPkgs: previousHaskellPkgs: { + anki-tools = null; ${pkg} = buildFromSdist (finalHaskellPkgs.callCabal2nix pkg fileInputs { }); + ipa = doJailbreak (unmarkBroken previousHaskellPkgs.ipa); }); } ); in { # `nix -L build` - packages = perSystem ({ haskellPackages, ... }: { + packages = perSystem ({ haskellPackages, pkgs, ... }: pkgs // { default = haskellPackages.${pkg}; }); # `nix -L develop` or `direnv allow` diff --git a/src/Wiktionary.hs b/src/Wiktionary.hs new file mode 100644 index 0000000..99c43f5 --- /dev/null +++ b/src/Wiktionary.hs @@ -0,0 +1,161 @@ +{-# LANGUAGE StrictData #-} + +module Wiktionary where + +-- import Data.List qualified as List +import Utils.Generics qualified as Gen +import Utils.JSON qualified as JSON +import Utils.Prelude +import Utils.SQL qualified as SQL + +import Control.Monad.Trans.Reader (ReaderT (..)) +import Control.Monad.Trans.State.Strict (StateT (..)) +import Database.SQLite.Simple.Internal (RowParser (..)) + +-- import Data.ByteString (ByteString) +-- import Database.SQLite3 qualified as SQL.Base +-- import Database.SQLite3.Direct qualified as SQL.Direct +-- import Database.SQLite3.Bindings qualified as SQL.Direct.Bindings +-- import Control.Exception (bracket) +-- import Data.Text.Encoding qualified as Text + +-- | Tries to follow the schema at: +-- https://kaikki.org/dictionary/errors/mapping/index.html +data Wiktionary = Wiktionary + { wiktionary_abbreviation :: Maybe [Abbreviation] + , wiktionary_anagrams :: Maybe [Anagram] + , wiktionary_antonyms :: Maybe JSON.Value + , wiktionary_categories :: Maybe [ShortText] + , wiktionary_derived :: Maybe JSON.Value + , wiktionary_etymology_examples :: Maybe JSON.Value + , wiktionary_etymology_texts :: [ShortText] + , wiktionary_forms :: Maybe [Form] + , wiktionary_holonyms :: Maybe JSON.Value + , wiktionary_hypernyms :: Maybe JSON.Value + , wiktionary_hyponyms :: Maybe JSON.Value + , wiktionary_lang :: Maybe ShortText + , wiktionary_lang_code :: Maybe ShortText + , wiktionary_meronyms :: Maybe JSON.Value + , wiktionary_notes :: Maybe JSON.Value + , wiktionary_paronyms :: Maybe JSON.Value + , wiktionary_pos :: Maybe ShortText + , wiktionary_pos_title :: Maybe ShortText + , wiktionary_proverbs :: Maybe JSON.Value + , wiktionary_raw_tags :: Maybe [ShortText] + , wiktionary_redirect :: Maybe ShortText + , wiktionary_related :: Maybe JSON.Value + , wiktionary_senses :: Maybe [Sense] + , wiktionary_sounds :: [Sound] + , wiktionary_synonyms :: Maybe [Synonym] + , wiktionary_tags :: Maybe [ShortText] + , wiktionary_title :: Maybe JSON.Value + , wiktionary_translations :: Maybe JSON.Value + , wiktionary_troponyms :: Maybe JSON.Value + , wiktionary_word :: Maybe ShortText + -- ^ Yes, the word can be missing, + -- eg. when `wiktionary_pos` is `"hard-redirect"`. + } + deriving (Eq, Show, Generic) + deriving + (JSON.ToJSON, JSON.FromJSON) + via (JSON.GenericallyWithOptions Wiktionary) + deriving + (SQL.ToRow {-, SQL.FromRow-}) + via (SQL.GenericallyWithOptions Wiktionary) + +instance SQL.FromRow Wiktionary where + fromRow = SQL.gfromRowWithErrorContext <&> Gen.to + +data Anagram = Anagram + { anagram_word :: ShortText + } + deriving (Eq, Show, Generic) + deriving + (JSON.ToJSON, JSON.FromJSON) + via (JSON.GenericallyWithOptions Anagram) + +data Sense = Sense + { sense_alt_of :: Maybe JSON.Value + , sense_categories :: Maybe [ShortText] + , sense_examples :: Maybe JSON.Value + , sense_form_of :: Maybe JSON.Value + , sense_glosses :: Maybe [ShortText] + , sense_note :: Maybe JSON.Value + , sense_raw_tags :: Maybe JSON.Value + , sense_tags :: Maybe JSON.Value + , sense_topics :: Maybe JSON.Value + } + deriving (Eq, Show, Generic) + deriving + (JSON.ToJSON, JSON.FromJSON) + via (JSON.GenericallyWithOptions Sense) + +data Synonym = Synonym + { synonym_alt :: Maybe JSON.Value + , synonym_raw_tags :: Maybe JSON.Value + , synonym_roman :: Maybe JSON.Value + , synonym_sense :: Maybe JSON.Value + , synonym_sense_index :: Maybe JSON.Value + , synonym_tags :: Maybe JSON.Value + , synonym_topics :: Maybe JSON.Value + , synonym_translation :: Maybe JSON.Value + , synonym_word :: ShortText + } + deriving (Eq, Show, Generic) + deriving + (JSON.ToJSON, JSON.FromJSON) + via (JSON.GenericallyWithOptions Synonym) + +data Abbreviation = Abbreviation + { abbreviation_raw_tags :: Maybe JSON.Value + , abbreviation_roman :: Maybe ShortText + , abbreviation_sense :: Maybe JSON.Value + , abbreviation_sense_index :: Maybe JSON.Value + , abbreviation_tags :: Maybe JSON.Value + , abbreviation_topics :: Maybe JSON.Value + , abbreviation_translation :: Maybe JSON.Value + , abbreviation_word :: Maybe ShortText + } + deriving (Eq, Show, Generic) + deriving + (JSON.ToJSON, JSON.FromJSON) + via (JSON.GenericallyWithOptions Abbreviation) + +data Form = Form + { form_form :: ShortText + , form_ipas :: Maybe [ShortText] + , form_raw_tags :: Maybe JSON.Value + , form_sense :: Maybe JSON.Value + , form_sense_index :: Maybe JSON.Value + , form_source :: Maybe ShortText + , form_tags :: Maybe [ShortText] + , form_hiragana :: Maybe ShortText + , form_roman :: Maybe ShortText + } + deriving (Eq, Show, Generic) + deriving + (JSON.ToJSON, JSON.FromJSON) + via (JSON.GenericallyWithOptions Form) + +data Sound = Sound + { sound_audio :: Maybe ShortText + , sound_homophone :: Maybe JSON.Value + , sound_ipa :: Maybe ShortText + , sound_mp3_url :: Maybe ShortText + , sound_oga_url :: Maybe ShortText + , sound_opus_url :: Maybe ShortText + , sound_ogg_url :: Maybe ShortText + , sound_flac_url :: Maybe ShortText + , sound_raw_tags :: Maybe [ShortText] + , sound_rhymes :: Maybe JSON.Value + , sound_roman :: Maybe JSON.Value + , sound_tags :: Maybe JSON.Value + , sound_wav_url :: Maybe ShortText + , sound_zh_pron :: Maybe JSON.Value + } + deriving (Eq, Show, Generic) + deriving + (JSON.ToJSON, JSON.FromJSON) + via (JSON.GenericallyWithOptions Sound) + +type LangCode = ShortText diff --git a/src/Worksheets/Writing/Rosetta.hs b/src/Worksheets/Writing/Rosetta.hs index 19dd27e..a02ffe9 100644 --- a/src/Worksheets/Writing/Rosetta.hs +++ b/src/Worksheets/Writing/Rosetta.hs @@ -66,24 +66,12 @@ instance HasTypeDefault RosettaDifficulty where , rosettaDifficultyHiddenPatterns = False } -data ObjectFit - = ObjectFitContain - | ObjectFitScaleDown - | ObjectFitCover - | ObjectFitFill - deriving (Eq, Ord, Show, Generic) -instance HasTypeDefault ObjectFit where - typeDefault = ObjectFitContain -instance ToCSS ObjectFit where - toCSS = \case - ObjectFitContain -> "contain" - ObjectFitScaleDown -> "scale-down" - ObjectFitCover -> "cover" - ObjectFitFill -> "fill" +cssBlockObjectFitCover :: CSSBlock +cssBlockObjectFitCover = ["object-fit" := "cover"] data RosettaPart = RosettaPart { rosettaPartPicture :: File.FilePath - , rosettaPartPictureFit :: ObjectFit + , rosettaPartPictureCSS :: CSSBlock , rosettaPartDescription :: ShortText , rosettaPartText :: ShortText , rosettaPartLangue :: Langue @@ -142,44 +130,32 @@ rosettaLandscape m = type RosettaDifficulties = Map UnicodeBlock RosettaDifficulty -rosettaDifficultiesLatinBig :: Modifier RosettaDifficulties rosettaDifficultiesLatinBig = - Map.unionWith (const mod) - $ [ Char.UnicodeBlockLatin latin := typeDefault & mod - | latin <- enumAll - ] - & fromList - where - mod v = - v - { rosettaDifficultyCharWidth = 1 & cm - , rosettaDifficultyCharHeight = 1 & cm - , rosettaDifficultyWordSpacing = 0.5 & cm - , rosettaDifficultyFontSize = 0.90 & cm - } - -mapMod keys mod = - Map.unionWith (const mod) - $ keys - & Map.fromSet (const $ typeDefault & mod) + mapInsertManyWithTypeDefault Char.unicodeBlockLatin \v -> + v + { rosettaDifficultyCharWidth = 1 & cm + , rosettaDifficultyCharHeight = 1 & cm + , rosettaDifficultyWordSpacing = 0.5 & cm + , rosettaDifficultyFontSize = 0.90 & cm + } rosettaDifficultiesCJKBig :: Modifier RosettaDifficulties rosettaDifficultiesCJKBig = - mapMod unicodeBlockCJK \v -> + mapInsertManyWithTypeDefault unicodeBlockCJK \v -> v - { rosettaDifficultyCharWidth = 1.35 & cm - , rosettaDifficultyCharHeight = 1.35 & cm + { rosettaDifficultyCharWidth = 1.50 & cm + , rosettaDifficultyCharHeight = 1.50 & cm , rosettaDifficultyWordSpacing = 0.5 & cm - , rosettaDifficultyFontSize = 1.25 & cm + , rosettaDifficultyFontSize = 1.40 & cm } rosettaDifficultiesLatinHidden :: Modifier RosettaDifficulties rosettaDifficultiesLatinHidden = - mapMod unicodeBlockLatin \v -> + mapInsertManyWithTypeDefault unicodeBlockLatin \v -> v{rosettaDifficultyHiddenPatterns = True} rosettaDifficultiesCJKHidden :: Modifier RosettaDifficulties rosettaDifficultiesCJKHidden = - mapMod unicodeBlockCJK \v -> + mapInsertManyWithTypeDefault unicodeBlockCJK \v -> v{rosettaDifficultyHiddenPatterns = True} lookupPinyins :: ChineseDict -> ShortText -> [ShortText] @@ -357,7 +333,7 @@ rosettaHTML chineseDict title Rosetta{..} = do H.span ! classes ["rosetta-cell-picture-description"] $ do rosettaPartDescription & H.toHtml H.img - ! styles ["object-fit" := rosettaPartPictureFit & toCSS] + ! styles rosettaPartPictureCSS ! HA.src ("file://" <> dataPath "images" rosettaPartPicture & toValue) H.div ! classes ["rosetta-cell", "writing-words"] $ do forM_ (rosettaPartText & rosettaTokenizer & groupByHoriz) \writingHoriz -> do diff --git a/tests/Spec.hs b/tests/Spec.hs index 5dd91cd..57942f9 100644 --- a/tests/Spec.hs +++ b/tests/Spec.hs @@ -1,19 +1,23 @@ {-# OPTIONS_GHC -w -Wall -fno-warn-missing-signatures -fno-warn-unused-imports #-} import Test.Syd -import Prelude qualified import Language.ChineseSpec qualified +import Utils.Prelude +import WiktionarySpec qualified import Worksheets.Writing.RosettaSpec qualified -main :: Prelude.IO () +main :: IO () main = sydTest spec spec = do - xdescribe "Language" do - describe "Chinese" do - Language.ChineseSpec.spec + -- xdescribe "Language" do + -- describe "Chinese" do + -- Language.ChineseSpec.spec describe "Worksheets" do describe "Writing" do describe "RosettaSpec" do Worksheets.Writing.RosettaSpec.spec + +-- xdescribe "Wiktionary" do +-- WiktionarySpec.spec diff --git a/tests/Worksheets/Writing/RosettaSpec.hs b/tests/Worksheets/Writing/RosettaSpec.hs index 4a463ff..04dc948 100644 --- a/tests/Worksheets/Writing/RosettaSpec.hs +++ b/tests/Worksheets/Writing/RosettaSpec.hs @@ -51,6 +51,8 @@ spec = aroundAll readDict do runRosetta "Fraise" fraise runRosetta "poupéeArielle" poupéeArielle runRosetta "poupéeBella" poupéeBella + runRosetta "Mûre" mûre + runRosetta "Framboise" framboise where readDict :: (Chinese.ChineseDict -> IO ()) -> IO () readDict = (Chinese.readChineseDict >>=) @@ -290,21 +292,21 @@ ponies = [ français $ typeDefault { rosettaPartPicture = "Poney/Horse-and-pony2.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartDescription = "" , rosettaPartText = "Les poneys sont petits mais costauds" } , anglais $ typeDefault { rosettaPartPicture = "Poney/A-girl-equestrian-athlete-jumps-on-a-horse-high-barrier-ss230301-768x448.jpg.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartDescription = "" , rosettaPartText = "Ponies are small but strong" } , mandarin $ typeDefault { rosettaPartPicture = "Poney/horse-pull.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartDescription = "" , rosettaPartText = "小马 虽 小 但 很 强壮" } @@ -317,21 +319,21 @@ poniesRaces1 = [ français $ typeDefault { rosettaPartPicture = "Poney/Shetland/Canva-Ponies-of-the-New-Forest-scaled.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartDescription = "Shetland Pony" , rosettaPartText = "Il existe environ 159 races de poneys" } , anglais $ typeDefault { rosettaPartPicture = "Poney/PoneyFrançaisDeSelle/pho11-1441004372-ulk-modele1.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartDescription = "Poney Français de Selle" , rosettaPartText = "There are approximately 159 pony breeds" } , mandarin $ typeDefault { rosettaPartPicture = "Poney/NorwegianFjord/shutterstock_2092896190-1024x683.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartDescription = "Norwegian Fjord Pony" , rosettaPartText = "有 大约 159 个 小马 品种" } @@ -344,21 +346,21 @@ poniesRaces2 = [ français $ typeDefault { rosettaPartPicture = "Poney/Haflinger/GettyImages-546441489-3087a0a3f3a0486f96e7e6d7eb0b6bc1.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartDescription = "Haflinger Pony" , rosettaPartText = "Il existe environ 159 races de poneys" } , anglais $ typeDefault { rosettaPartPicture = "Poney/Dartmoor/GettyImages-149824058-ee7fd8a5e9984f5a9dc73c5916a238aa.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartDescription = "Dartmoor Pony" , rosettaPartText = "There are approximately 159 pony breeds" } , mandarin $ typeDefault { rosettaPartPicture = "Poney/Connemara/eaa17d54a2978f5962edc405f0beabb7.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartDescription = "Connemara Pony" , rosettaPartText = "有 大约 159 个 小马 品种" } @@ -371,21 +373,21 @@ poniesRaces3 = [ français $ typeDefault { rosettaPartPicture = "Poney/" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartDescription = "Pony" , rosettaPartText = "Il existe environ 159 races de poneys" } , anglais $ typeDefault { rosettaPartPicture = "Poney/Dartmoor/GettyImages-149824058-ee7fd8a5e9984f5a9dc73c5916a238aa.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartDescription = "Dartmoor Pony" , rosettaPartText = "There are approximately 159 pony breeds" } , mandarin $ typeDefault { rosettaPartPicture = "Poney/Connemara/eaa17d54a2978f5962edc405f0beabb7.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartDescription = "Connemara Pony" , rosettaPartText = "有 大约 159 个 小马 品种" } @@ -397,19 +399,19 @@ culicoides = [ français $ typeDefault { rosettaPartPicture = "Culicoides/Blood-Feeding-Culicoides-Midges.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartText = "Les moucherons culicoides sont des vampires infectieuses" } , anglais $ typeDefault { rosettaPartPicture = "Culicoides/Mosquito_(Ochlerotatus_annulipes)_and_Midge_(Culicoides_impunctatus)_biting_human_(me).avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartText = "Culicoides midges are infectious vampires" } , mandarin $ typeDefault { rosettaPartPicture = "Culicoides/CSIRO_ScienceImage_1791_SEM_of_a_biting_midge_Culicoides_brevitarsis.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartText = "库蠓属 具有 传染性 的 吸血鬼" } ] @@ -427,7 +429,7 @@ fraise = , anglais $ typeDefault { rosettaPartPicture = "Fraise/OIP.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartText = "Strawberry's fruits are the achenes" } , mandarin @@ -470,7 +472,7 @@ poupéeBella = , anglais $ typeDefault { rosettaPartPicture = "LaBelleEtLaBête/disney-live-action-02.avif" - , rosettaPartPictureFit = ObjectFitCover + , rosettaPartPictureCSS = cssBlockObjectFitCover , rosettaPartText = "Bella the doll and Maya the girl" } , mandarin @@ -480,3 +482,53 @@ poupéeBella = } ] } +mûre = + rosettaLandscape + $ rosetta + { rosettaParts = + [ français + $ typeDefault + { rosettaPartPicture = "Mûre/Bee-Feeding-on-Blackberry-Blossom.avif" + , rosettaPartPictureCSS = cssBlockObjectFitCover + , rosettaPartText = "Les fruits de la mûre sont des drupéoles" + } + , anglais + $ typeDefault + { rosettaPartPicture = "Mûre/blackberry-anatomy.avif" + , rosettaPartText = "Blackberry's fruits are drupelets" + } + , mandarin + $ typeDefault + { rosettaPartPicture = "Mûre/berryblack.avif" + , rosettaPartPictureCSS = cssBlockObjectFitCover + , rosettaPartText = "黑莓 的 果实 是 小 核果" + } + ] + } +framboise = + rosettaLandscape + $ rosetta + { rosettaParts = + [ français + $ typeDefault + { rosettaPartPicture = "Framboise/ghows-SR-6c5aadd8-13b2-7679-e053-0100007f79b5-ad44228b.avif" + , rosettaPartPictureCSS = + cssBlockObjectFitCover + <> ["object-position" := "left center"] + , rosettaPartText = "" + } + , anglais + $ typeDefault + { rosettaPartPicture = "Framboise/framboise-schema-fr.avif" + , rosettaPartText = "" + } + , mandarin + $ typeDefault + { rosettaPartPicture = "Framboise/RR.avif" + , rosettaPartPictureCSS = + cssBlockObjectFitCover + <> ["object-position" := "right bottom"] + , rosettaPartText = "" + } + ] + } diff --git a/tests/Worksheets/Writing/RosettaSpec/Fraise/rosetta.html b/tests/Worksheets/Writing/RosettaSpec/Fraise/rosetta.html index 21c5556..855ed62 100644 --- a/tests/Worksheets/Writing/RosettaSpec/Fraise/rosetta.html +++ b/tests/Worksheets/Writing/RosettaSpec/Fraise/rosetta.html @@ -1,92 +1,92 @@ Fraise
-
+
L
e
s
f
r
u
i
t
s
d
e
@@ -158,9 +158,9 @@ size:A4 landscape;
a
r
e
t
h
e
a
c
h
e
n
e
s
-
-
cǎo
méi
草
莓
草
莓
-
de
的
的
-
guǒ
shí
果
实
果
实
-
shì
是
是
-
shòu
guǒ
瘦
果
瘦
果
\ No newline at end of file +
+
cǎo
méi
草
莓
草
莓
+
de
的
的
+
guǒ
shí
果
实
果
实
+
shì
是
是
+
shòu
guǒ
瘦
果
瘦
果
\ No newline at end of file diff --git a/tests/Worksheets/Writing/RosettaSpec/ponies/rosetta.html b/tests/Worksheets/Writing/RosettaSpec/ponies/rosetta.html index 8b6d9c3..24149ef 100644 --- a/tests/Worksheets/Writing/RosettaSpec/ponies/rosetta.html +++ b/tests/Worksheets/Writing/RosettaSpec/ponies/rosetta.html @@ -1,92 +1,92 @@ ponies
-
+
A
r
i
e
l
l
e
l
a
p
o
u
p
é
e
e
t
M
e
r
l
i
n
l
e
g
a
r
ç
o
n
-
+
A
r
i
e
l
t
h
e
d
o
l
l
a
n
d
M
e
r
l
i
n
t
h
e
b
o
y
-
-
wá
wá
娃
娃
娃
娃
+
+
wá
wá
娃
娃
娃
娃
A
r
i
e
l
l
e
-
hé
和
和
nán
hái
男
å­©
男
å­©
méi
lín
梅
林
梅
林
\ No newline at end of file +
hé
和
和
nán
hái
男
å­©
男
å­©
méi
lín
梅
林
梅
林
\ No newline at end of file diff --git "a/tests/Worksheets/Writing/RosettaSpec/poup\303\251eBella/rosetta.html" "b/tests/Worksheets/Writing/RosettaSpec/poup\303\251eBella/rosetta.html" index 18e9c37..0a83a6a 100644 --- "a/tests/Worksheets/Writing/RosettaSpec/poup\303\251eBella/rosetta.html" +++ "b/tests/Worksheets/Writing/RosettaSpec/poup\303\251eBella/rosetta.html" @@ -1,92 +1,92 @@ poupéeBella
-
+
B
e
l
l
a
l
a
p
o
u
p
é
e
e
t
M
a
y
a
@@ -153,7 +153,7 @@ size:A4 portrait;
t
h
e
d
o
l
l
a
n
d
M
a
y
a
t
h
e
g
i
r
l
-
-
wá
wá
娃
娃
娃
娃
+
+
wá
wá
娃
娃
娃
娃
B
e
l
l
a
-
hé
和
和
nǚ
hái
女
å­©
女
å­©
mǎ
yǎ
马
雅
马
雅
\ No newline at end of file +
hé
和
和
nǚ
hái
女
å­©
女
å­©
mǎ
yǎ
马
雅
马
雅
\ No newline at end of file diff --git a/worksheets.cabal b/worksheets.cabal index d39dd30..645b505 100644 --- a/worksheets.cabal +++ b/worksheets.cabal @@ -13,7 +13,7 @@ copyright: Julien Moutinho -- PVP: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change -version: 0.0.0.20250603 +version: 0.0.0.20250617 stability: experimental category: Worksheets synopsis: Worksheets @@ -75,7 +75,7 @@ common library-deps import: build-depends: , aeson >=2.1.2.1 - , anki-tools + , anki-tools >=0.2 , array , attoparsec , attoparsec-aeson @@ -86,11 +86,15 @@ common library-deps , bytestring , cassava , containers + , data-default + , direct-sqlite , filepath , generic-data + , ipa , pretty-simple , safe-decimal , scientific + , sqlite-simple , text >=2.1 , text-short , transformers @@ -103,12 +107,17 @@ library autogen-modules: Paths_worksheets exposed-modules: Language.Chinese + Language.English + Language.French Utils.Char + Utils.Generics Utils.HTML Utils.JSON Utils.Prelude Utils.Probability + Utils.SQL Utils.TypeDefault + Wiktionary Worksheets.Writing.Rosetta other-modules: Paths_worksheets @@ -128,6 +137,7 @@ test-suite worksheets-tests other-modules: Language.ChineseSpec Paths_worksheets + WiktionarySpec Worksheets.Writing.RosettaSpec build-depends: -- 2.47.2