{"id":25180501,"url":"https://github.com/rsdc2/haskell-odt-writer","last_synced_at":"2025-04-04T04:46:59.735Z","repository":{"id":276360386,"uuid":"703884413","full_name":"rsdc2/haskell-odt-writer","owner":"rsdc2","description":"Interface for composing and writing OpenDocument Text (.odt) files in Haskell","archived":false,"fork":false,"pushed_at":"2025-02-08T11:24:33.000Z","size":195,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-08T11:24:52.946Z","etag":null,"topics":["haskell","monads","monoids","opendocument-text-document","writer"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rsdc2.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-12T05:40:51.000Z","updated_at":"2025-02-08T07:32:02.000Z","dependencies_parsed_at":"2025-02-08T11:35:00.748Z","dependency_job_id":null,"html_url":"https://github.com/rsdc2/haskell-odt-writer","commit_stats":null,"previous_names":["rsdc2/haskell-odt","rsdc2/haskell-odt-writer"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsdc2%2Fhaskell-odt-writer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsdc2%2Fhaskell-odt-writer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsdc2%2Fhaskell-odt-writer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsdc2%2Fhaskell-odt-writer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rsdc2","download_url":"https://codeload.github.com/rsdc2/haskell-odt-writer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247123098,"owners_count":20887260,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["haskell","monads","monoids","opendocument-text-document","writer"],"created_at":"2025-02-09T16:18:37.251Z","updated_at":"2025-04-04T04:46:59.718Z","avatar_url":"https://github.com/rsdc2.png","language":"Haskell","funding_links":[],"categories":["Haskell"],"sub_categories":[],"readme":"# Haskell ODT Writer\n\n## Overview\n\nHaskell ODT Writer provides an interface in Haskell for reading and writing Open Document Format `.odt` files.\n\nThe program is set up to enable the user to compose their own `.odt` files using Haskell syntax. \n\n## Installing and building\n\nSo far I have only tested this process on Linux (Ubuntu), not Windows or MacOS. You can install with [Stack](https://docs.haskellstack.org/en/stable/). I installed Haskell and Stack with [GHCup](https://www.haskell.org/ghcup/). \n\n## Build and test environment\n\nHaskell ODT Writer has been built and tested on GHC 9.4.7 using Stack 2.11.1.\n\n### 1. Clone and `cd` into the repo\n\n```\n$ git clone https://github.com/rsdc2/haskell-odt\n$ cd haskell-odt\n```\n\n### 2. Build\n\n```\n$ stack build\n```\n\n### 3. Run the tests\n\n```\n$ stack test\n```\n\n### 4. Run the Main app\n\n```\n$ stack run\n```\n\n## Composing OpenDocument Text documents\n\nAn OpenDocument Text file is a Zip archive comprising a directory structure of `.xml` files. From a writer's perspective the two most important files are:\n\n- `content.xml` which carries the text content of the file\n- `styles.xml` which carries the style information\n\nThese are the two files that `haskell-odt-writer` allows the user to write to.\n\nIn the simplest case, you want simply to write some text content into a file that can be read e.g. by LibreOffice / OpenOffice Writer. In [`Main.hs`](app/Main.hs) you will find a function with the following signature:\n\n```haskell\ncontent :: Writer ODT ()\n```\n\nThis functions provides the content of your document. There are two primary functions to be aware of:\n\n- `writeTextSpan`\n- `writeNewPara`\n- `writePara` \n\n#### `writeTextSpan :: TextStyle -\u003e T.Text -\u003e Writer ODT ()`\n\nThis function takes a `TextStyle` and a section of text, applies this style to the text, and appends it to the document. For example, the following will write out \"Hello world.\" to the document without any formatting:\n\n```haskell\n\ncontent :: Writer ODT ()\ncontent = do\n    writeTextSpan normal \"Hello world.\"\n```\n\nIf you want to apply some formatting, you can use a `TextStyle` other than `normal`, e.g.:\n\n```haskell\ncontent :: Writer ODT ()\ncontent = do\n    writeTextSpan italic \"Hello world.\"\n```\n\nThis will write \"_Hello world._\" to the document, this time in italics.\n\nTo append further text to the document, simply add further lines to the function, e.g.:\n\n```haskell\ncontent :: Writer ODT ()\ncontent = do\n    writeTextSpan italic \"Hello world. \"\n    writeTextSpan bold \"This is bold text.\"\n```\n\nIn this case, the document will comprise a single line: \"*Hello world.* **This is bold text.**\"\n\n#### `writeNewPara :: Writer ODT ()`\n\nIf you want to start a new paragraph, use the `writeNewPara` function, which takes no arguments. You can then follow this with further `TextSpan`s:\n\n```haskell\ncontent :: Writer ODT ()\ncontent = do\n    writeTextSpan italic \"Hello world. \"\n    writeTextSpan bold \"This is bold text.\"\n    writeNewPara\n    writeTextSpan normal \"This is normal text.\"\n```\n\nThe text \"This is normal text.\" will appear in a new paragraph.\n\n\n#### `writePara :: ParaStyle -\u003e T.Text -\u003e Writer ODT ()`\n\nTo write a new section of text as a new paragraph with a _paragraph style_ (as opposed to a _text style_), use the `writePara` function, e.g.:\n\n```haskell\n\n```haskell\ncontent :: Writer ODT ()\ncontent = do\n    writeTextSpan italic \"Hello world. \"\n    writePara normalPara \"This text is in normal paragraph style.\"\n    writePara italicPara \"This text is in italic paragraph style.\"\n```\n\n\n## Saving the document to disk\n\nThere are two main functions which can write a new `.odt` file to disk, use the function `writeNewODT`.\n\n#### `writeNewODT :: Folderpath -\u003e Filename -\u003e Writer ODT () -\u003e IO ()`\n\nWrites a new document to disk with all styling applied as _direct_ formatting. For example, applying bold formatting using this function would be equivalent to pressing the `B` button in LibreOffice Writer, e.g.:\n\n```haskell\nwriteNewODT \"./examples/output\" \"SimpleExample.odt\" content\n```\n\nThis will save the content we have described in `content` to a file `SimpleExample.odt` in the `./examples/output` folder.\n\n\u003c!-- - `writeNewODTWithStyles`: Writes a new document to disk with all styling applied via _styles_. Applying e.g. bold formatting using this function would be equivalent to using the `Strong Emphasis` style in LibreOffice Writer.  --\u003e\n\n\u003c!-- ## Key concepts --\u003e\n\n## Acknowledgements \n\nThe inspiration for modelling an `.odt` file as a monoid, and for using the `Writer` monad for document composition, came from the [HaTeX](https://gitlab.com/daniel-casanueva/haskell/HaTeX) project, which provides an interface in Haskell for composing and otherwise analysing LaTeX documents. \n\n## Further information\n\n- [OpenDocument (Wikipedia)](https://en.wikipedia.org/wiki/OpenDocument)\n\n- [OpenDocument technical specification (Wikipedia)](https://en.wikipedia.org/wiki/OpenDocument_technical_specification)\n\n- [OpenDocument standard (OASIS Open)](https://www.oasis-open.org/2021/06/16/opendocument-v1-3-oasis-standard-published/)\n\n## Dependencies and licenses\n\n- [bytestring](https://hackage.haskell.org/package/bytestring-0.12.1.0/docs/Data-ByteString.html): BSD-style\n- [containers](https://hackage.haskell.org/package/containers): [BSD-3](https://hackage.haskell.org/package/containers-0.7/src/LICENSE)\n- [directory](https://hackage.haskell.org/package/directory): [BSD-3](https://hackage.haskell.org/package/directory-1.3.9.0/src/LICENSE)\n- [extra](https://hackage.haskell.org/package/extra): [BSD-3](https://hackage.haskell.org/package/extra-1.8/src/LICENSE)\n- [mtl](https://hackage.haskell.org/package/mtl): [BSD-3](https://hackage.haskell.org/package/mtl-2.3.1/src/LICENSE)\n- [text](https://hackage.haskell.org/package/text-2.1.2/docs/Data-Text.html): BSD-style\n- [time](https://hackage.haskell.org/package/time): [BSD-2](https://hackage.haskell.org/package/time-1.14/src/LICENSE)\n- [xml](https://hackage.haskell.org/package/xml): [BSD-3](https://hackage.haskell.org/package/xml-1.3.14/src/LICENSE)\n- [xml-conduit](https://hackage.haskell.org/package/xml-conduit): [MIT](https://hackage.haskell.org/package/xml-conduit-1.10.0.0/src/LICENSE)\n- [zip-archive](https://hackage.haskell.org/package/zip-archive-0.4.3.2/docs/Codec-Archive-Zip.html): BSD-3\n- [HUnit](https://hackage.haskell.org/package/HUnit): [BSD-3](https://hackage.haskell.org/package/HUnit-1.6.2.0/src/LICENSE)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frsdc2%2Fhaskell-odt-writer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frsdc2%2Fhaskell-odt-writer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frsdc2%2Fhaskell-odt-writer/lists"}