jgm/djot.js

Revise filter API

jgm opened this issue · 1 comments

jgm commented

Perhaps it should work as in pandoc:

  • If you don't return a value, the node doesn't change.
  • If you do, the node is replaced by the node you return.
  • If you return an array of nodes, they are spliced in at the position of the node. (This can be used to delete elements by returning an empty array.)
jgm commented

Commit 8380cd8 contains some steps towards this.
The main problem I see is in figuring out a new way to handle "stop traversal," rather than returning true.

Here are some comments on the new API, to be inserted in filter.ts eventually:

 *
 * The filters we've looked at so far modify nodes in place by
 * changing one of their properties (`text`).
 * Sometimes we'll want to replace a node with a different kind of
 * node, or with several nodes, or to delete a node.  In these
 * cases we can end the filter function with a `return`.
 * If a single AST node is returned, it will replace the element
 * the filter is processing.  If an array of AST nodes is returned,
 * they will be spliced in to replace the element.  If an empty
 * array is returned, the element will be deleted.
 *
 * // This filter replaces certain Symb nodes with
 * // formatted text.
 * const substitutions = {
 *   mycorp: [ { tag: "str", text: "My Corp" },
 *             { tag: "superscript",
 *               [ { tag: "str", text: "(TM)" } ] } ],
 *   myloc: { tag: "str", text: "Coyote, NM" }
 *   };
 * return {
 *   symb: (e) => {
 *     const found = substitutions[e.alias];
 *     if (found) {
 *       return found;
 *     }
 *   }
 * }
 *
 * // This filter replaces all Image nodes with their descriptions.
 * return {
 *   image: (e) => {
 *     return e.children;
 *   }
 * }