=====Advanced Formatting and code generation===== //All of the features on this page are now installed as a [[WikkaBetaFeatures | beta features]] on this server as of 2005-06-12.// >>==See also:== //core// ~-CompatibilityCode ~-AdvancedFormOpen ~-GenerateUniqueId ~-ArrayToList ~-ArrayToColumns //formatter// ~-ImprovedFormatter ~-WantedFormatters ~-TableofcontentsAction ~-WikkaExtensibleMarkup ~-AcronymFormatter >>This is the development page (or rather a //hub// for a number of separate development pages) for advanced Wikka formatting and other new or enhanced code "responsible" for **generating valid XHTML in Wikka pages**. While the Formatter takes user-supplied source code in Wikka "markup" and turns it into XHTML, there are several actions and handlers also produce XHTML output directly: using core utility methods for this generation process helps to make such generated code structural, valid and consistent. This page deals with both aspects of Wikka since although they have different operation they are closely related in their purpose (and the Formatter also makes use of some of the core utility methods for its work).::c:: The code written by JavaWoman (all now installed on this server as a beta feature) addresses several issues of the current formatter and other code generation. In particular, it fixes a number of small formatting bugs, and adds new important features - like automatic generation of ##id##s for headers and forms - required both for XHTML compliance and for (later) extensions such as the ability to link to page //fragments// (often implemented through //anchors// though we've chosen the XHTML-strict compliant method of using //fragment **id**s//), which in turn will enable //TOC//'s. More consistent generated code and generated ids will also enable advanced styling through CSS. ====What's new==== Much of this really isn't visible on the "surface", and you can't suddenly do new things **yet**; what we get instead is a number of **enabling** features that (will) make other things (visible things) possible, as well as ways to generate code more consistently and reliably. Some of it really is "**formatting**" (given page source with Wikka formatting codes, generating valid XHTML from it), some of it is just utility methods that can be called upon by the formatter as well as other methods, actions and handlers to help **generating** valid XHTML that provides "hooks" for styling and other things. These "enabling" features mostly take the form of new and enhanced methods in the [[Docs:WikkaCore | Wikka core]]: ===The core: [[WikkaCore | wikka.php]]=== ==##html_entity_decode()##== This is new [[CompatibilityCode | compatibility code]] (similar to ##mysql_real_escape_string()##) to provide functionality used by ##wakka.php## when generating ids for headings: the function ##html_entity_decode()## is available as of PHP 4.3 but for older versions we provide a (near) equivalent alternative; ==##""FormOpen()""##== A more advanced version of the ##""FormOpen()""## method (see AdvancedFormOpen) which uses the new ##makeId()## method (see GenerateUniqueId); it also supports more types of forms, including forms that allow file uplaods. The ##""FormOpen()""## method is already used by many actions and handlers but with the extensions **all** code generating a form really should use this method together with its ##""FormClose()""## counterpart since all forms type are now provided for. This will ensure consistent and valid code and make it easier to style forms. ==##""makeId()""##== A new ##""makeId()""## method with some supporting code (see GenerateUniqueId). From the docblock for the method: ~//Although - given Wikka accepts embedded HTML - it cannot be guaranteed that an id generated by this method is unique, it tries its best to make it unique: ~~- ids are organized into groups, with the group name used as a prefix; ~~- if an id is specified it is compared with other ids in the same group; if an identical id exists within the same group, a sequence suffix is added, otherwise the specified id is accepted and recorded as a member of the group ~~- if no id is specified (or an invalid one) an id will be generated, and given a sequence suffix if needed ~For headings, it is possible to derive an id from the heading content to support this, any embedded whitespace is replaced with underscores to generate a recognizable id that will remain (mostly) constant even if new headings are inserted in a page. ~ The method supports embedded HTML as well: as long as the formatter passes each id found in embedded HTML through this method it can take care that the id is valid and unique. This works as follows: ~~- indicate an 'embedded' id with group 'embed' ~~- NO prefix will be added for this reserved group ~~- ids will be recorded and checked for uniqueness and validity ~~- invalid ids are replaced ~~- already-existing ids in the group are given a sequence suffix ~The result is that as long as the already-defined id is valid and unique, it will be remain unchanged (but recorded to ensure uniqueness overall).// ==##""makeList()""## and ##""makeMemberList()""##== Two new utility methods **##makeList()##** and ##""makeMemberList()""## are so far only a draft form (see ArrayToList); they are able to generate a list from an array, with ##id## and / or ##class## attributes. Only 'flat' arrays supported for now; the intention is to enhance it with recursion to generate nested lists as well. From the docblock for the ##""makeList()""## method: ~// Given an array, this method builds a simple unordered or ordered list with an id. Only a (simple) array is required which will generate an unordered list; optionally id, class, type of list and an indent level can be specified. For type 'menu' an unordered list is generated but with an id in group 'menu' instead of 'ul' or 'ol': this enables the list being styled as a menu.// Several existing actions could make use of these utilities, and work is in progress to adapt them to do this. More on ArrayToList. ==##""makeCols()""## and ##""makeMemberCols()""##== Analogous to **##makeList()##** and ##""makeMemberList()""##, two equally new utility methods ##""makeCols()""## and ##""makeMemberCols()""## provide a similar API to generate columns of data instead of a single list (see ArrayToColumns). The columns are implemented as floated ##div##s instead of as a layout table, providing more structural and accessible code. From the docblock for the ##""makeCols()""## method: ~//Given an array and number of columns, this method builds vertically-arranged columns (meaning they are read vertically, one by one) implemented as floated divs. Column width is derived from the specified number of columns, implemented as an embedded style because it's dynamically generated; left float is added to the style (hardcoded for now but alignment could become an option later).// Again several existing pieces of Wikka code could make use of these, with work in progress to implement this. More on ArrayToColumns. ===The Formatter: ##./formatters/wakka.php##=== The Formatter has the responsibility to translate user-provided page code into valid XHTML. It's not perfect at this but it's getting a little better. Since some of the intended improvements required quite a bit of digging into the code, some work was also done to make that code a bit more readable, while the digging work also unearthed a few existing bugs (including unrecorded ones) that could now be solved. All of this does not make an //advanced Formatter// but it does make our Formatter //more advanced//. To make generating valid XHTML from Wikka code more reliable, a complete rewrite would actually be needed, but for now the following will at least get us closer, and help enable new features as well: ~- using single quotes wherever possible making [[RegEx]]es and generated HTML easier to read; ~- better closing of open tags at end of document, including open indents and lists (a long-standing bug!) ''Now improved'' ~- better handling of nested lists so change of list "type" is actually detected and coded correctly; also produces nicely-formatted HTML code for lists and indents now, especially more readable for nested lists. ''New!'' ~- escaping single & (not part of an entity) (another long-standing problem); ~- ability to nest one type of float within another (so a right float can contain a left float and vice versa) ~- handling ids (and making them unique) as provided in embedded code, using the ##""makeId()""## method; ~- creating ids for headings based on content ('afterburner' type formatting so this //includes// originally embedded code); this code not only uses the ##""makeId()""## method but also the ##html_entity_decode()## method in PHP versions older than 4.3. For details and code, see ImprovedFormatter. ====The code ==== //core// ~-**##html_entity_decode()##** - see CompatibilityCode ~-**##""FormOpen()""##** - See AdvancedFormOpen ~-**##""makeId()""##** - see GenerateUniqueId ~-**##""makeList()""##** and **##""makeMemberList()""##** - see ArrayToList ~-**##""makeCols()""##** and **##""makeMemberCols()""##** - see ArrayToColumns //formatter// ~-The Formatter - see ImprovedFormatter ---- CategoryDevelopmentFormatters CategoryDevelopmentCore