Skip to content

Automatic document type #59

@Elliria

Description

@Elliria

My setup:

  • Formiko 1.4.3
  • m2r 0.3.1
  • docutils 0.20.1
  • Kubuntu 24.04 LTS
  • Xorg

Before I begin, thank you for an amazing tool!

Up until today, I was able to open both Markdown and RST files in Formiko and both rendered correctly. Today, however, when I opened a Markdown file that Formiko has opened and rendered correctly thousands of times, my ~/.config/formiko.ini file spontaneously changed the parser = rst line to parser = json, leading to this JSONDecodeError displayed in the right pane of Formiko:

JSON Error!

Expecting value: line 1 column 1 (char 0)

Renaming the ~/.config/formiko.ini file to ~/.config/formiko.ini.bak caused Formiko to recreate the ~/.config/formiko.ini file on its next run and that new file contains the parser = rst line.

Since renaming the file caused the file to be restored, that is no longer an issue, and since the issue may have been a Kubuntu issue rather than a Formiko issue, I didn't report it separately and am including it here just for reference as to what is leading me down this particular rabbit-hole.

With that freshly-generated config file in place, Formiko opens and renders RST files correctly. Markdown files, however, are now either rendered as plain text or throw exceptions or give errors, depending on their content. As an example, a new Markdown file with just the # Hello world line is rendered in plain text in Formiko instead of as a heading. The more complex Markdown file mentioned above that Formiko has opened and rendered for me successfully thousands of times now throws this exception:

Exception Error!

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/formiko/renderer.py", line 374, in render_output
    html = publish_string(**kwargs).decode('utf-8')
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/core.py", line 460, in publish_string
    output, publisher = publish_programmatically(
                        ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/core.py", line 722, in publish_programmatically
    output = publisher.publish(enable_exit_status=enable_exit_status)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/core.py", line 234, in publish
    self.document = self.reader.read(self.source, self.parser,
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/readers/__init__.py", line 70, in read
    self.parse()
  File "/usr/lib/python3/dist-packages/docutils/readers/__init__.py", line 76, in parse
    self.parser.parse(self.input, document)
  File "/usr/lib/python3/dist-packages/docutils/parsers/rst/__init__.py", line 184, in parse
    self.statemachine.run(inputlines, document, inliner=self.inliner)
  File "/usr/lib/python3/dist-packages/docutils/parsers/rst/states.py", line 170, in run
    results = StateMachineWS.run(self, input_lines, input_offset,
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/statemachine.py", line 233, in run
    context, next_state, result = self.check_line(
                                  ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/statemachine.py", line 445, in check_line
    return method(match, context, next_state)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/parsers/rst/states.py", line 1322, in enumerator
    newline_offset, blank_finish = self.nested_list_parse(
                                   ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/parsers/rst/states.py", line 317, in nested_list_parse
    state_machine.run(block, input_offset, memo=self.memo,
  File "/usr/lib/python3/dist-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/statemachine.py", line 233, in run
    context, next_state, result = self.check_line(
                                  ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/statemachine.py", line 445, in check_line
    return method(match, context, next_state)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/parsers/rst/states.py", line 2568, in enumerator
    listitem, blank_finish = self.list_item(match.end())
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/parsers/rst/states.py", line 1296, in list_item
    self.nested_parse(indented, input_offset=line_offset,
  File "/usr/lib/python3/dist-packages/docutils/parsers/rst/states.py", line 280, in nested_parse
    state_machine.run(block, input_offset, memo=self.memo,
  File "/usr/lib/python3/dist-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/statemachine.py", line 233, in run
    context, next_state, result = self.check_line(
                                  ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/statemachine.py", line 445, in check_line
    return method(match, context, next_state)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/parsers/rst/states.py", line 2777, in underline
    msg = self.reporter.severe(
          ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/utils/__init__.py", line 239, in severe
    return self.system_message(self.SEVERE_LEVEL, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/docutils/utils/__init__.py", line 197, in system_message
    raise SystemMessage(msg, level)
docutils.utils.SystemMessage: :255: (SEVERE/4) Unexpected section title.

fi
```

Interestingly, the section of the document that it's complaining about is the last two lines of this section of the document (it believes that fi is or wants to be a section-header):

7. Set up pyenv:
   ```bash
   if [ ! -d "$HOME/.pyenv" ]; then
       curl https://pyenv.run | bash
       export PYENV_ROOT="$HOME/.pyenv"
       export PATH="$PYENV_ROOT/bin:$PATH"
       eval "$(pyenv init - bash)"
       echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
       echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
       echo 'eval "$(pyenv init - bash)"' >> ~/.bashrc
   fi
   ```

If I replace the parser = rst line in the ~/.config/formiko.ini file with the parser = md line, Formiko correctly renders all of my Markdown files correctly regardless of their complexity, but it then fails to render RST files correctly.

In summary, even though the ~/.config/formiko.ini file has been successfully recreated to solve my initial issue and it now contains default content, Markdown files can no longer be rendered properly in Formiko without editing the ~/.config/formiko.ini file and manually changing parser = rst to parser = md.

Formiko doesn't currently seem to offer a parser = auto setting or an easily-discernible way to list more than one parser (for example: parser = md, rst or parser = md rst, etc.) that would configure Formiko to render each file based on the extension in its filename. Please consider adding such an option so that Formiko can switch engines automatically.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions