python-frontmatter icon indicating copy to clipboard operation
python-frontmatter copied to clipboard

Feature request: preserve order of YAML front matter when writing content back to file

Open jimmcslim opened this issue 1 year ago • 2 comments

It looks like the frontmatter is alphabetically sorted when it is written back out. It would be great if it could preserve the order of existing items, while adding new items to the end.

jimmcslim avatar Jun 07 '24 23:06 jimmcslim

I am using the following handler to preserve order:

import re

import frontmatter as fm
import oyaml

class OYAMLHandler(fm.default_handlers.BaseHandler):
    """
    Load and export YAML metadata using oyaml [1].

    [1]: https://github.com/wimglenn/oyaml
    """

    FM_BOUNDARY = re.compile(r"^-{3,}\s*$", re.MULTILINE)
    START_DELIMITER = END_DELIMITER = "---"

    def load(self, fm: str, **kwargs: object) -> Any:
        """
        Parse YAML front matter. This uses oyaml.SafeLoader by default.
        """
        kwargs.setdefault("Loader", oyaml.SafeLoader)
        return oyaml.load(fm, **kwargs)  # type: ignore[arg-type]

    def export(self, metadata: dict[str, object], **kwargs: object) -> str:
        """
        Export metadata as YAML. This uses oyaml.SafeDumper by default.
        """
        kwargs.setdefault("Dumper", oyaml.SafeDumper)
        kwargs.setdefault("default_flow_style", False)
        kwargs.setdefault("allow_unicode", True)

        metadata_str = oyaml.dump(metadata, **kwargs).strip()  # type: ignore[call-overload]
        return fm.util.u(metadata_str)  # ensure unicode

Example usage:

with open(filename) as f:
    note = fm.load(f, handler=OYAMLHandler())

# ...

with open(filename, 'wb') as f:
    fm.dump(note, f, handler=OYAMLHandler())

cadent-mrichman avatar Mar 26 '25 18:03 cadent-mrichman

I came here searching for this same problem.

sort_keys=False worked for me.

The thread about it is here: https://github.com/eyeseast/python-frontmatter/issues/26#issuecomment-799024484

nexgen avatar May 30 '25 09:05 nexgen