{"id":16489752,"url":"https://github.com/phfaist/flm","last_synced_at":"2025-03-23T12:34:35.880Z","repository":{"id":44348436,"uuid":"482643089","full_name":"phfaist/flm","owner":"phfaist","description":"A Flexible Latex-like Markup (FLM) language","archived":false,"fork":false,"pushed_at":"2025-02-21T17:01:20.000Z","size":1188,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-18T20:40:43.346Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phfaist.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2022-04-17T22:03:15.000Z","updated_at":"2025-02-21T17:01:24.000Z","dependencies_parsed_at":"2024-07-24T13:51:29.520Z","dependency_job_id":"a2b4e66f-1a74-491e-8919-21be16a42642","html_url":"https://github.com/phfaist/flm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phfaist%2Fflm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phfaist%2Fflm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phfaist%2Fflm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phfaist%2Fflm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phfaist","download_url":"https://codeload.github.com/phfaist/flm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245104460,"owners_count":20561377,"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":[],"created_at":"2024-10-11T13:45:16.903Z","updated_at":"2025-03-23T12:34:35.452Z","avatar_url":"https://github.com/phfaist.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# A Flexible Latex-Like Markup (FLM) language\n\nThis package provides a simple parser and formatter for a custom markup language\nthat is inspired by LaTeX syntax.\n\nThe syntax of FLM is essentially a subset of standard LaTeX commands, including\nmacros, environments, and some characters that have a special meaning; these\nfeatures are parsed in a loosely similar fashion to usual LaTeX code.\n\nThe framework is meant to be very easily extendible and customizable.  The\nparser is based on the upcoming version 3 of\n[*pylatexenc*](https://github.com/phfaist/pylatexenc)\n(currently in pre-release on pypi).\n\nFLM is used to write the contents of the [Error Correction\nZoo](https://errorcorrectionzoo.org/) in a way that is intuitive for scientists,\nflexible, and robust.  It is easily extensible and closely resembles the LaTeX\nlangauge that many scientists are familiar with.  FLM pushes further one of the\ncore insights of LaTeX, namely, that the code should *describe* document\ncontents in an intuitive way, as a markup language, while disregarding as much\nas possible the details of how that contents will be typeset.  The final\ntypesetting is fully customizable, e.g., through CSS styling of its HTML output\n(including the use of templates).\n\nI intended to call this project \"LLM\" as an acronym for Latex-Like Markup, but\nhad to revise my choice after the astronomical growth of large language models.\n\nYou can install FLM with pip:\n```bash\n$ pip install flm-core\n```\n\nExample `mydocument.flm`:\n```latex\n---\ntitle: Kitaev's Surface Code\n---\n\\section{Kitaev's Surface Code}\n\nThe \\emph{stabilizers} of the \\textit{surface code} on the 2-dimensional\ntorus are generated by star operators \\(A_v\\) and plaquette operators\n\\(B_p\\).  Each star operator is a \\textbf{product} of four Pauli-\\(X\\)\noperators on the edges adjacent to a vertex \\(v\\) of the lattice; each\nplaquette operator is a product of four Pauli-\\(Z\\) operators applied to\nthe edges adjacent to a face, or plaquette, \\(p\\) of the lattice\n(\\ref{figure:toric-code-operators}).\n\n\\begin{figure}\n  \\includegraphics{toric-code-operators}\n  \\caption{Stabilizer generators and logical operators of the 2D surface\n    code on a torus.  The star operators \\(A_v\\) and the plaquette\n    operators \\(B_p\\) generate the stabilizer group of the toric code.\n    The logical operators are strings that wrap around the torus.}\n  \\label{figure:toric-code-operators}\n\\end{figure}\n\n...\n```\n\nTo compile your document into an HTML page, use:\n```bash\n$ flm mydocument.flm -o mydocument.html --format=html --template=simple\n```\n\nYou can then open the `mydocument.html` file in your browser.\n\n# This is work in progress!\n\nThis project is still early in an active development stage, and there might\nstill be a few bugs around. You can expect the API to still change pretty\ndrastically.  Feel free to share ideas!\n\n# Use as a command-line tool\n\nYou can use `flm` in command-line mode to compile your documents:\n```bash\n$ flm mydocument.flm\n```\n\nRun `flm --help` to get a list of options. They should be fairly\nstandard and/or self-explanatory:\n```bash\n# output to file mydocument.html, format HTML, including skeleton\n# HTML structure with minimal CSS.\n$ flm mydocument.flm -o mydocument.html --format=html --template=simple\n```\n\nAvailable formats are `html`, `text`, `latex`, and `markdown`.  Formats\n`text`, `markdown`, and `latex` are very experimental!  (You can also\ngenerate `pdf` output with the options `--workflow=runlatexpdf --format=pdf`\nif your system has a standard LaTeX distribution such as TeXLive installed)\n\n- **Additional HTML Templates:**\n  The `--template=` option can be used to change the template used to render the\n  document.  See also the\n  [*flm-templates*](https://github.com/phfaist/flm-templates) extension package\n  for some additional templates and template engines.  You can try:\n  ```\n  \u003e pip install flm-templates flm-htmlplus\n  ```\n  and then\n  ```\n  \u003e flm mydocument.flm -o output.html -w flm_htmlplus -P 'pkg:flm_templates' -t sunset\n  ```\n  Or try the template `-t oldtextbook`.\n\n- **Citations from arXiv \u0026 DOI:**\n  Automatically fetch citations from the arXiv, DOI x-references, or other\n  sources using the [*flm-citations*](https://github.com/phfaist/flm-citations)\n  extension package (see README file there).  Install the extension package\n  using pip:\n  ```\n  \u003e pip install flm-citations\n  ```\n  And then try to compile, e.g., the following FLM document:\n  ```yaml\n  ---\n  $import:\n    - pkg:flm_citations\n  ---\n  \\section{Introduction}\n  Let's cite Kitaev's surface code~\\cite{doi:10.1070/RM1997v052n06ABEH002155,doi:10.1007/978-1-4615-5923-8_19,arXiv:quant-ph/9707021}. ...\n  ```\n\n- **Theorems and proofs:** Use the environments\n  ``\\begin{theorem}..\\end{theorem}``, ``{lemma}``, ``{proposition}``,\n  ``{definition}``, ``{remark}``, etc. for typesetting theorems.  You can pin\n  labels to theorem statements ``\\label{thm:XYZ}`` (use the `thm:` or `x:`\n  prefixes regardless of the theorem type, so you can easily change it without\n  having to update the label).  These environments accept an optional argument\n  so you can specify a title, e.g. ``\\begin{theorem}[Euler's theorem]\n  ... \\end{theorem}``.  Typeset proofs with ``\\begin{proof} ... \\end{proof}``.\n  The proof's optional argument enjoys an additional syntax: use\n  ``\\begin{proof}[*thm:XYZ] ...`` to typeset `Proof (Theorem 3)` (with the\n  correct theorem reference using its label, which must match the one specified\n  to the theorem's ``\\label`` command).  Use ``\\begin{proof}[**thm:XYZ] ...`` to\n  simply typeset `Proof` as usual, but in this way you have the information about\n  which theorem the proof is directly at hand; if you later move it around there\n  is no ambiguity as to which theorem the proof is associated with.  It is also\n  the same syntax as supported by the [phfthm latex\n  package](https://github.com/phfaist/phfqitltx) which is able to produce\n  hyperlinks between theorems and their proofs.\n\n## Document Front Matter\n\nFLM Documents can contain YAML front matter that specify (i) options for the FLM\nparser, (ii) which features to enable, and (iii) additional document metadata such\nas a title.\n```yaml\n---\ntitle: 'My FLM document'\nflm:\n   parsing:\n     dollar_inline_math_mode: True\n   features:\n     endnotes:\n       categories:\n         - category_name: footnote\n           counter_formatter: unicodesuperscript\n           heading_title: 'Footnotes'\n           endnote_command: 'footnote'\n---\n\n\\section{Greeting}\nHello, \\emph{world}. Inline math can now also be typeset\nas $a$ and $b$.  ...\n\n```\n\n### Imports\n\nYou can use the `$import:` directive to import a configuration from an\nexternal file, URL, or extension package:\n```yaml\n$import:\n  - my-flm-config.yaml # merge my-flm-config.yaml into this config.\n\n# you can still specify configuration to merge with here ...\n...\nflm:\n   ...\n```\n\nThe `$import:` target can specify multiple configurations to import.  Each list\nitem can be a absolute or relative file path (`$import: 'my-flm-config.yaml'` or\n`$import: /path/to/my/flm-config.yaml`), a URL (`$import:\nhttps://example.com/my/flm-config.yaml`), or a fully qualified python package\nname introduced with ``pkg:package_name`` (e.g., `$import: pkg:flm_citations`).\nIf a package name is specified to the `$import` directive, the package is loaded\nand the default FLM configuration is extracted from it and included (the\n`flm_default_import_config` attribute of the module is read; it is assumed to be\na dictionary or a callable that returns a dictionary).  You can optionally\nfollow the package name by a path to specify submodules/attributes to read\ninstead of `flm_default_import_config`; e.g., ``pkg:mypackage/foo/bar`` will\nimport the module `mypackage` and import the configuration dictionary stored in\n``mypackage.foo.bar``.  FLM extention plugin/package authors can use this\nfeature to offer preset customization configurations that can easily be included\nwith ``pkg:some_flm_extension_package/some/preset/name``.\n\n\n### Parser configuration\n\nHere's a basic parser configuration that you can adapt:\n```yaml\nflm:\n  parsing:\n    # Enable/Disable comments as in LaTeX, led by ‘%%’\n    enable_comments: true\n    # This string initiates a comment up to the end of\n    # the line, if comments are enabled.  By default we\n    # require TWO '%' signs to avoid accidental comments\n    # (e.g., \"... is up 10% from ...\")\n    comment_start: '%%'\n    # Enable/Disable math mode with $ signs as in LaTeX\n    # in addition to \\( ...\\)\n    dollar_inline_math_mode: false\n    # Force parsing of the content in block-level mode\n    # (paragraphs).  Here ‘null’ means to auto-detect\n    force_block_level: null\n```\n\n### Renderer configuration (`html`, `text`, `latex`, `markdown`)\n\nHere's a basic renderer configuration that you can adapt **for HTML output**\n(`--format=html`):\n```yaml\nflm:\n  renderer:\n    html:\n      use_link_target_blank: false\n      html_blocks_joiner: ''\n      # use ‘headings_tags_by_level: null’ for defaults\n      heading_tags_by_level:\n        1: h1\n        2: h2\n        3: h3\n        4: span\n        5: span\n        6: span\n      inline_heading_add_space: true\n```\n\nHere's a basic renderer configuration that you can adapt **for text output**\n(`--format=text`):\n```yaml\nflm:\n  renderer:\n    text:\n      display_href_urls: true\n```\n\nHere's a basic renderer configuration that you can adapt **for LaTeX output**\n(`--format=latex`):\n```yaml\nflm:\n  renderer:\n    latex:\n      heading_commands_by_level:\n        1: \"section\"\n        2: \"subsection\"\n        3: \"subsubsection\"\n        4: \"paragraph\"\n        5: \"subparagraph\"\n        6: null\n```\n\nHere's a basic renderer configuration that you can adapt **for Markdown output**\n(`--format=markdown`):\n```yaml\nflm:\n  renderer:\n    markdown:\n      use_target_ids: 'github' # or 'anchor' or 'pandoc' or null\n```\n\n\n### Features and their configuration\n\nMany FLM features are organized explicitly into feature classes which can be\nenabled or disabled at wish.  Features include:\n\n- enumeration (`\\begin{enumerate}...\\end{enumerate}`) and itemization\n  (`\\begin{itemize}...\\end{itemize}`) lists\n  \n- floats: figures and tables (`\\begin{figure}...\\end{figure}`)\n\n- headings (`\\section{...}` etc.)\n\n- etc.\n\nFeatures can be selected and configured directly in the FLM config metadata.  For instance\nthe following configuration is extracted from the default feature configuration when you run\nFLM:\n```yaml\nflm:\n  features:\n    # list features that should be available here.\n    enumeration:\n      enumeration_environments:\n        enumerate:\n          # here null means to use defaults\n          counter_formatter: null\n        itemize:\n          counter_formatter:\n            - \"\\u2022\"\n            - '-'\n            - \"\\u25B8\"\n    refs: {}\n    endnotes:\n      categories:\n        - category_name: footnote\n          counter_formatter: alph\n          endnote_command: footnote\n          heading_title: Footnotes\n      render_options:\n        include_headings_at_level: 1\n        set_headings_target_ids: true\n        endnotes_heading_title: null\n        endnotes_heading_level: 1\n    floats:\n      float_types:\n        - counter_formatter: Roman\n          float_caption_name: Fig.\n          float_type: figure\n          content_handlers: ['any', 'includegraphics', 'cells']\n        - counter_formatter: Roman\n          float_caption_name: Tab.\n          float_type: table\n          content_handlers: ['cells']\n\n    defterm: {}\n    graphics: {}\n\n    substmacros:\n      definitions:\n        macros:\n          # Loosely equivalent to \\newcommand\\mymacro{Substitution \\emph{code}}\n          mymacro:\n            content: 'Substitution \\emph{code}'\n          # \\newcommand\\greet[2][Hello]{#1, #2!}\n          greet:\n            arguments_spec_list: '[{'\n            content: '#1, #2!'\n            default_argument_values:\n              1: 'Hello'\n          # Same, but with named arguments -\u003e \\greeet\n          greeet:\n            arguments_spec_list:\n              - parser: '['\n                argname: 'the_greeting'\n              - parser: '{'\n                argname: 'person_name'\n            default_argument_values:\n              the_greeting: 'Hello'\n            content: '\\textit{#{the_greeting}: #{person_name}}'\n          # Macro with different definitions in text mode and in math mode:\n          Ident:\n            content:\n              textmode: null\n              mathmode: '\\mathbb{1}'\n```\n\n## Additional Features such as *Citations*\n\nAdditional features can be imported in the flm config.  They can reside in other\npython packages.  Some day I'll properly document how to write new features.\nFor now, check out the examples in `flm/feature/xxx.py` (and keep in mind that\nthe APIs are still likely to change!).\n\nTo include for instance the citations feature provided by the\n[flm-citations](https://github.com/phfaist/flm-citations) package, install that\npackage and use the config:\n```yaml\n$import:\n  - pkg:flm_citations\nbibliography:\n  - bibpreset.yaml\n  - anotherbibtest.json\n```\nCitations are organized by citation prefix and are automatically retrieved\ndepending on the type of citation.  By default:\n- Citations of the form `arxiv:\u003carXiv ID\u003e` are automatically retrieved from the arXiv API\n- Citations of the form `doi:\u003cDOI\u003e` are automatically retrieved from [doi.org](https://doi.org/)\n- Citations of the form `manual:{Manual citation}` add the manual citation itself as a citation\n- Citations of the form `bib:key` look up `key` in one of the specified bibliography files.  The\n  bibliography files are expected to be CSL-JSON or CSL-YAML files. (Sorry, no bibtex for now.)\n\nYou can of course configure all of that manually. Check out the code in the\n[`flm-citations`](https://github.com/phfaist/flm-citations) repo for more insight.  Doc will\nhopefully come soon.\n\n\n# Using the `flm` package\n\nNeeds doc.\n\n## Example. Converting FLM to HTML\n\nNote: Math is simply marked with `\u003cspan class=...\u003e` tags for use with\n[MathJax](https://www.mathjax.org/).\n\nExample:\n```py\nfrom flm.flmenvironment import make_standard_environment\nfrom flm.stdfeatures import standard_features\nfrom flm.fragmentrenderer.html import HtmlFragmentRenderer\n\nenviron = make_standard_environment(features=standard_features())\n\n# suppose we have fragments of FLM text\nfragment_1 = environ.make_fragment(r'Hello, \\emph{world}.')\nfragment_2 = environ.make_fragment(\n    r'''Here's a question: \\(1+2=?\\)\n\\begin{enumerate}[(a)]\n\\item 1\n\\item 2\n\\item 3\n\\end{enumerate}\n'''\n)\n\n# we can define a callback to render these fragments within an\n# HTML page. The advantage of doing so is that different fragments\n# can \"see\" each other! (E.g., for \\ref's, etc.) This feature can\n# be useful especially in combination with template engines.\ndef render_fn(render_context):\n    return (\n        \"\u003cmain\u003e\\n\"\n        + \"\u003cdiv\u003e\" + fragment_1.render(render_context) + \"\u003c/div\u003e\\n\"\n        + fragment_2.render(render_context) + \"\\n\"\n        + \"\u003c/main\u003e\"\n    )\n\ndoc = environ.make_document(render_fn)\n\nfragment_renderer = HtmlFragmentRenderer()\nresult_html, render_context = doc.render(fragment_renderer)\n\nprint(result_html)\n# *** Prints:\n#\n# \u003cmain\u003e\n# \u003cdiv\u003eHello, \u003cspan class=\"textit\"\u003eworld\u003c/span\u003e.\u003c/div\u003e\n# \u003cp\u003eHere\u0026#x27;s a question: \u003cspan class=\"inline-math\"\u003e\\(1+2=?\\)\u003c/span\u003e\u003c/p\u003e\n# \u003cdl class=\"enumeration enumerate\"\u003e\u003cdt\u003e(a)\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e1\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e(b)\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e2\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e(c)\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e3\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\n# \u003c/main\u003e\n```\n\n\n# A Javascript FLM library\n\nYou can transpile the core part of this library to Javascript using Transcrypt.\nSee [the `flm-js` subfolder](flm-js/README.md) for more details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphfaist%2Fflm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphfaist%2Fflm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphfaist%2Fflm/lists"}