i would expect a call to publish_string() and publish_doctree() + publish_from_doctree() with exactly the same arguments to result in identical output, but this is not the case. sample program to illustrate the issue:
from docutils.core import *
rst = '''\
My Document
===========
.. meta::
:my-custom-header: my-custom-value
'''
settings = {
'output_encoding': 'UTF-8',
'stylesheet_path': None,
}
sOut = publish_string(rst, writer_name='html', settings_overrides=settings)
dtree = publish_doctree(rst)
dOut = publish_from_doctree(dtree, writer_name='html', settings_overrides=settings)
# this assert passes
assert '<meta content="my-custom-value" name="my-custom-header" />' in sOut
# these asserts fail
assert '<meta content="my-custom-value" name="my-custom-header" />' in dOut
assert sOut == dOut
note that besides the meta directive missing in the doctree version, everything else looks the same.
The "meta" directive is "HTML-only", it creates a pending node that is removed by the "Filter" transform if the writer is not "HTML".
It seems the "Filter" transform is run by publish_doctree() but should be run by publish_from_doctree() instead because only then the writer is known.
Actually, the "Filter" transform should be run by both, publish_doctree() and publish_from_doctree() but only apply changes if the
component_typeis "reader" in the first case and ifcomponent_typeis "writer" in the second.Patches welcome.
The components.Filter transform is only used for post-processing the "meta" directive's content. When
<meta>becomes a standard Docutils doctree node (as planned), the transform is no longer required and the described behaviour will be fixed."meta" is now a standard node and the "filter" directive no longer required.
Fixed in Docutils 0.18. Thanks again for the report.