-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replacing multiple children in parent #96
Comments
You might be missing is a Also, it's not best practice to modify the parent from the child function, and I'm not really sure if it's needed. Can you just create a new element directly and return that? (or I might be missing something) |
Thanks for the quick reply. Maybe I'm not understanding the process correctly. If this is the case, then surely you can't just return a modified parent to change it? My solution/hack at the moment, is to record any elements that need to be deleted, then def action(element, doc):
...
doc.to_delete.setdefault(element.parent, set()).update(delete_content)
def prepare(doc):
# type: (Doc) -> None
doc.to_delete = {}
def finalize(doc):
# type: (Doc) -> None
for element, delete in doc.to_delete.items():
element.content = [e for e in element.content if e not in delete]
del doc.to_delete |
I don't want to create, I want to destroy! (lol), i.e. I want to remove elements neighbouring the current element, whilst potentially keeping that element the same |
As far as I recall, to destroy I write |
Yeh the only pain with that, is that you have to decide ahead of time what the possible parent types of the element are. Btw, if your interested I've almost finished what I was trying to achieve in this module of my ipypublish package, which effectively is an enhanced port of pandoc-xnos to panflute :) |
I wrote a small convenience function, to list all elements that might contain a particular element: import inspect
import panflute as pf
def find_allowed(targets, allow_meta=False):
"""
>>> find_allowed([pf.Para()])
[panflute.elements.BlockQuote,
panflute.elements.Definition,
panflute.elements.Div,
panflute.elements.Doc,
panflute.elements.ListItem,
panflute.elements.Note,
panflute.elements.TableCell]
"""
allowed = []
all_elements = inspect.getmembers(
pf.elements,
predicate=(lambda e: inspect.isclass(e) and issubclass(e, pf.Element)))
base_elements = inspect.getmembers(
pf.base,
predicate=(lambda e: inspect.isclass(e) and issubclass(e, pf.Element)))
for name, el in all_elements:
if (name, el) in base_elements:
continue
try:
inst = el(*targets)
except TypeError:
continue
if not hasattr(inst, 'content'):
continue
if el.__name__.startswith("Meta") and not allow_meta:
continue
allowed.append(el)
return allowed |
A final (maybe!) note on this, I ended up using the helper function below. FYI, my whole filter is explained here: https://ipypublish.readthedocs.io/en/latest/markdown_cells.html import panflute as pf
def get_pf_content_attr(container, target):
panflute_inline_containers = [
pf.Cite,
pf.Emph,
pf.Header,
pf.Image,
pf.LineItem,
pf.Link,
pf.Para,
pf.Plain,
pf.Quoted,
pf.SmallCaps,
pf.Span,
pf.Strikeout,
pf.Strong,
pf.Subscript,
pf.Superscript,
pf.Table,
pf.DefinitionItem
]
panflute_block_containers = (
pf.BlockQuote,
pf.Definition,
pf.Div,
pf.Doc,
pf.ListItem,
pf.Note,
pf.TableCell
)
if issubclass(target, pf.Cite):
# we assume a Cite can't contain another Cite
if not isinstance(container, tuple(panflute_inline_containers[1:])):
return False
if issubclass(target, pf.Inline):
if isinstance(container, tuple(panflute_inline_containers)):
if isinstance(container, pf.Table):
return "caption"
elif isinstance(container, pf.DefinitionItem):
return "term"
else:
return "content"
else:
return False
if issubclass(target, pf.Block):
if isinstance(container, tuple(panflute_block_containers)):
return "content"
else:
return False
raise TypeError("target not Inline or Block: {}".format(target))
def action(element, doc):
content_attr = get_pf_content_attr(element, pf.RawInline)
if not content_attr:
return None
content = getattr(element, content_attr)
...
setattr(element, content_attr, content)
return element |
Heya, could you suggest a best-practice way to do this:
Basically, I want to replace
<cite data-cite="cite_key">text</cite>
with\cite{cite_key}
.My approach so far is to find the opening tag, then traverse right to find the closing tag:
However, this does not replace the parent content in the final doc!?
The text was updated successfully, but these errors were encountered: