Edgewall Software

Changes between Version 6 and Version 7 of TracDev/Proposals/WikiParserFormatterSplit


Ignore:
Timestamp:
Jun 20, 2010, 12:02:23 PM (14 years ago)
Author:
Christian Boos
Comment:

#ImplementationNotes resuming work on the topic

Legend:

Unmodified
Added
Removed
Modified
  • TracDev/Proposals/WikiParserFormatterSplit

    v6 v7  
    3232
    3333
    34 == Implementation ==
     34== Implementation Notes ==
    3535
    3636I've chosen a tree-based approach, in which the wiki text is first converted to a Wiki DOM tree,
     
    4040This is the approach outlined in #4431.
    4141
    42 More specifically, the !WikiDomNode class hierarchy is used to model the inheritance relations between the various types of nodes. This enables to setup ''embedding rules'', specifying which node can be placed into which others. Therefore the structure of the document and its consistency can be ensured.
     42//More specifically, the !WikiDomNode class hierarchy is used to model the inheritance relations between the various types of nodes. This enables to setup ''embedding rules'', specifying which node can be placed into which others. Therefore the structure of the document and its consistency can be ensured.// not sure about this anymore (cboos)
    4343
    4444The inheritance relationships are also quite useful on the formatter level, as this way one can easily specify some specific handling for a group of node types.
    4545More importantly, if a new type of node is added (say by a `IWikiSyntaxProvider`), the existing formatters can also be augmented by custom rendering callbacks for those new nodes. If some formatters aren't updated (say because there are special formatters contributed by some unrelated plugins), they'll be able to handle those new nodes based on their parent type.
    4646
    47 As a snapshot of the work in progress, here are the new interfaces:
    48  - `IWikiSyntaxProvider`, for providing new syntax. [[br]]
    49    The default Trac syntax is in most part defined by syntax provider components.
    50    The interface remains compatible with Trac [milestone:0.10]
    51    (lesson learned ;-) )
    52  - `IWikiFormatterContributor`, for providing new or extending existing
    53    formatting flavors. [[br]]
    54   The default Trac formatters are entirely provided by formatter contributors.
    55   [[br]]  (''new interface'')
    56 
    57 {{{
    58 #!python
    59 class IWikiSyntaxProvider(Interface):
    60  
    61     def get_wiki_syntax():
    62         """Return an iterable that provides additional wiki syntax.
    63 
    64         A new syntax rule is a `(priority, regexp, callback)` triple.
    65         The `priority` is used to globally order the rules.
    66 
    67         The `regexp` must be of the form `"(?P<...>...)"`, where
    68         `<...>` contains a globally unique name that will be used
    69         to identify the rule.
    70 
    71         The `callback` expects a `parser` argument of type `WikiParser`,
    72         and will use it to participate to the construction of the
    73         Wiki DOM tree.
    74        
    75         Before 0.11, the additional wiki syntax corresponded
    76         simply to a `(regexp, callback)` pair. The priority of such
    77         rules is set to `50`, which introduces them after the simple
    78         text style rules and before the other ones, as they used to be.
    79 
    80         However, the old `callback` function was of the form
    81         `handler(formatter, ns, match, fullmatch)`, i.e. it was
    82         actually expected to take care of the ''formatting'' as well.
    83         """
    84  
    85     def get_link_resolvers():
    86         """Generate new handlers for new TracLinks prefixes.
    87 
    88         A handler is a `(namespace, callback)` pair, where the
    89         `callback` is a function expected a `parser` argument
    90         (the `WikiParser` instance currently driving the parsing).
    91 
    92         Before 0.11, the generated value were `(namespace, formatter)`
    93         pairs, where the `formatter` was a function of the form
    94         `fmt(formatter, ns, target, label)`, and would return some
    95         HTML fragment.
    96         The `label` is already HTML escaped, whereas the `target` is not.
    97         """
    98 
    99     def get_valid_parents():
    100         """Generate rules for element embedding.
    101 
    102         Each rule is of the form `(nodetype, valid_parent_nodetypes)`,
    103         which means that an instance node of the given `nodetype` type
    104         can be parented in instance nodes of the `valid_parent_nodetypes`
    105         types.
    106 
    107         Example: `(Inline, Anchor)` means that any `Inline` node can
    108                  be set to be a child of an `Anchor` node.
    109 
    110         (`valid_parent_nodetypes` can be a single class or a tuple
    111         of classes, all subclasses of `WikiDomNode`)
    112         """
    113 
    114 
    115 class IWikiFormatterContributor(Interface):
    116 
    117     def get_wiki_formatters():
    118         """Generate `(flavor, nodetype, formatter_callback)` triples.
    119 
    120         This enables the wiki system to register the `formatter_callback`
    121         for handling `nodetype` nodes when rendering a parse tree to
    122         the specified `flavor` kind of output.
    123         If for a given node, there's no callback registered directly for
    124         its class, a callback registered for one of its ancestor class
    125         will be used, following the method resolution order.     
    126 
    127         The `formatter_callback` itself is a function accepting a
    128         `Formatter` argument and the `WikiDomNode` instance currently
    129         being rendered and must return a result which is appropriate
    130         for the kind of formatting being done.
    131         """
    132 }}}
    133 
    134 The main utility functions for parsing and formatting wiki text will be:
    135 {{{
    136 #!python
    137 
    138 # -- Utility functions
    139 
    140 def parse_wiki(ctx, wikitext):
    141     """Parse `wikitext` and produce a Wiki DOM tree.
    142 
    143     Return the `WikiDocument` root node of that tree.
    144     """
    145     return WikiSystem(ctx.env).parse(wikitext)
    146 
    147 def format_to(flavor, ctx, wikidom, **kwargs):
    148     """Format to `flavor` the given `wikidom` parsed wiki text,
    149     in the given `ctx`.
    150 
    151     `wikidom` can be simply text instead of a Wiki DOM tree,
    152     and it will be parsed on the fly.
    153     """
    154     return WikiSystem(ctx.env).format(ctx, wikidom, flavor, **kwargs)
    155 
    156 def format_to_html(ctx, wikidom, escape_newlines=False):
    157     return WikiSystem(ctx.env).format(ctx, wikidom, 'default',
    158                                       escape_newlines=escape_newlines)
    159 # etc.
    160 }}}
    161 
    162  ''implementations details to be updated as the code progresses''
     47Some early ideas are visible in [[.@6#Implementation|version 6]] of this document.
     48
     49The parsing logic is described in VerticalHorizontalParsing.
    16350
    16451=== The !WikiSystem ===
     
    17360  the `IWikiSyntaxProvider`s and to maintain the environment global state of the parser.
    17461
    175  !WikiEngine::
    176   An engine is a transient object whose purpose is to maintain some state during the parsing of a given wiki text,
    177   and produce a Wiki DOM tree.
     62 !WikiDocument::
     63  A document correspond to the parsing of a given wiki text.
     64  It contains a Wiki DOM tree.
    17865
    17966 !WikiDomNode::