text: /*______________
  |       ______  |   U I Z E    J A V A S C R I P T    F R A M E W O R K
  |     /      /  |   ---------------------------------------------------
  |    /    O /   |    MODULE : Uize.Doc.Simple Package
  |   /    / /    |
  |  /    / /  /| |    ONLINE : http://www.uize.com
  | /____/ /__/_| | COPYRIGHT : (c)2004-2014 UIZE
  |          /___ |   LICENSE : Available under MIT License or GNU General Public License
  |_______________|             http://www.uize.com/license.html
  */
  
  /* Module Meta Data
  	type: Package
  	importance: 6
  	codeCompleteness: 100
  	docCompleteness: 2
  */
  
  /*?
  	Introduction
  		The =Uize.Doc.Simple= package provides a method for building HTML documentation from documentation that is written in the Wikitext-like SimpleDoc format.
  
  		*DEVELOPERS:* `Chris van Rensburg`
  */
  
  Uize.module ({
  	name:'Uize.Doc.Simple',
  	required:[
  		'Uize.Data.Simple',
  		'Uize.Templates.List',
  		'Uize.Str.Lines',
  		'Uize.Str.Limit',
  		'Uize.Templates.Adoptable',
  		'Uize.Array.Sort',
  		'Uize.Util.Html.Encode',
  		'Uize.Json'
  	],
  	builder:function () {
  		'use strict';
  
  		var
  			/*** Variables for Scruncher Optimization ***/
  				_undefined,
  				_string = 'string',
  				_limitLength = Uize.Str.Limit.limitLength,
  				_htmlEncode = Uize.Util.Html.Encode.encode,
  
  			/*** General Variables ***/
  				_bulletCharRegExpStr = '[-\\*~:\\.]',
  				_bulletCharRegExp = new RegExp (_bulletCharRegExpStr),
  				_onlyBulletCharRegExp = new RegExp ('^\\s*' + _bulletCharRegExpStr + '\\s*$'),
  				_orderingStyleRegExpStr = '([@#\\+a-zA-Z]|\\d+)',
  				_orderingStyleRegExp = new RegExp (_orderingStyleRegExpStr),
  				_listItemPrefixRegExp = new RegExp (
  					'^([<\\(\\{\\[]*\\s*' + _orderingStyleRegExpStr + '?\\s*[>\\)\\}\\]]*\\s*' + _bulletCharRegExpStr + '*\\s+)'
  				),
  				_sectionAliasesRegExp = /\s*~{2,}\s*/,
  				_objectTypeRegExp = /^\s*<<\s*([^<]*?)\s*>>\s*[\n\r]/,
  				_objectParamsIsJsonRegExp = /^\s*\{/,
  				_builtInObjectTemplates = {
  					html:function (_input) {
  						return _input.code;
  					},
  					image:function (_input,_indent,_indentChars) {
  						var
  							_titleAsAttributeValue = _htmlEncode (_input.title || ''),
  							_subtitleAsAttributeValue = _htmlEncode (_input.subtitle || ''),
  							_titleAndSubtitle = _titleAsAttributeValue && _subtitleAsAttributeValue,
  							_urlAsAttributeValue = _htmlEncode (_input.url),
  							_imageAlt =
  								_titleAsAttributeValue +
  								(_titleAndSubtitle && ' (') + _subtitleAsAttributeValue + (_titleAndSubtitle && ')')
  						;
  						return [
  							_indent + '<div class="image">',
  								_indent + _indent + '<a href="' + _urlAsAttributeValue + '">',
  									_indent + _indent + _indent + '<img' +
  										' src="' + _urlAsAttributeValue + '"' +
  										' title="' + _imageAlt + '"' +
  										' alt="' + _imageAlt + '"' +
  										(_input.width ? ' width="' + _htmlEncode (_input.width) + '"' : '') +
  										(_input.height ? ' height="' + _htmlEncode (_input.height) + '"' : '') +
  									'/>',
  								_indent + _indent + '</a>',
  								_indent + _indent + '<div>',
  									(
  										_titleAsAttributeValue &&
  										(_indent + _indent + _indent + '<span class="imageTitle">' + _titleAsAttributeValue + '</span>')
  									),
  									(
  										_subtitleAsAttributeValue &&
  										(_indent + _indent + _indent + '<span class="imageSubtitle">' + _subtitleAsAttributeValue + '</span>')
  									),
  								_indent + _indent + '</div>',
  							_indent + '</div>'
  						].join ('\n');
  					},
  					/* NOTE:
  						"metadata" is a reserved object block type (for which there is no template)
  					*/
  					samplecode:function (_input) {
  						return '<pre class="sample-code">' + _toSampleCode (_input.code || '') + '</pre>';
  					},
  					table:function (_input,_indent,_indentChars) {
  						var
  							_htmlChunks = [_indent + '<table class="data">'],
  							_title = _input.title,
  							_rows = _input.data,
  							_rowsLength = _rows.length
  						;
  						_title &&
  							_htmlChunks.push (
  								_indent + _indentChars + '<tr class="title">',
  								_indent + _indentChars + _indentChars +
  									'<td' + (_rowsLength ? (' colspan="' + _rows [0].length + '"') : '') + '>' +
  										_toSampleCode (_title) +
  									'</td>',
  								_indent + _indentChars + '</tr>'
  							)
  						;
  						for (var _rowNo = -1, _cols; ++_rowNo < _rowsLength;) {
  							_htmlChunks.push (_indent + _indentChars + '<tr' + (_rowNo ? '' : ' class="heading"') + '>');
  							_cols = _rows [_rowNo];
  							for (var _colNo = -1, _colsLength = _cols.length, _col; ++_colNo < _colsLength;)
  								_htmlChunks.push (
  									_indent + _indentChars + _indentChars +
  									'<td>' + _toSampleCode (_cols [_colNo]) + '</td>'
  								)
  							;
  							_htmlChunks.push (_indent + _indentChars + '</tr>');
  						}
  						_htmlChunks.push (_indent + '</table>');
  						return _htmlChunks.join ('\n');
  					},
  					widget:function (_input,_indent,_indentChars,_simpleDocBuildParams) {
  						var _widgetProperties = Uize.copy ({html:'shell'},_input);
  						if (_widgetProperties.name == _undefined)
  							_widgetProperties.name =
  								'widget' +
  								(_simpleDocBuildParams.totalWidgets = (_simpleDocBuildParams.totalWidgets || 0) + 1)
  						;
  						return Uize.Str.Lines.indent (Uize.Templates.Adoptable.process (_widgetProperties),1,_indent);
  					}
  				},
  				_slashCharCodesMap = {47:1,92:1} // 47 is forward slash, 92 is backslash
  		;
  
  		/*** Utility Functions ***/
  			var _sectionIdToPathMap = {};
  			function _getSectionPathFromId (_sectionId) {
  				return (
  					_sectionIdToPathMap [_sectionId] ||
  					(_sectionIdToPathMap [_sectionId] = Uize.map (_sectionId.split ('_'),'+value'))
  				);
  			}
  
  		/*** Public Static Methods (implementation) ***/
  			function _build (_params) {
  				/* PARAMETERS:
  					canonicalizePeerSections
  						A boolean, indicating whether or not the contents of multiple peer sections of the same name should be consolidated into a single section of that name.
  					contentsList
  						A boolean, specifying whether or not a contents list should be included in the generated HTML document. Defaults to true, if not specified.
  					data
  						the data object to be converted to HTML
  					indentChars
  						the characters to use for each level of indentation
  					headingNumberingSeparator
  						the characters to be placed between a heading's numbering and the heading's title, as in the following examples...
  							1.2.3. This is the heading
  							1.2.3: This is the heading
  							1.2.3 - This is the heading
  					headingNumberingDelimiter
  						the characters to be placed between each point level in heading numbering, as in the following examples...
  							1.2.3 - This is the heading
  							1-2-3 - This is the heading
  							1 > 2 > 3 - this is the heading
  					pathToRoot
  						A string, specifying the relative path to the root of the Web site that will be hosting the generated HTML document, from where the generated HTML document will be located.
  					result
  						A string, specifying the form in which the result should be returned. When the value ='full'= is specified, an object is returned with the following structure...
  
  						.............................................................................................
  						{
  							html:htmlSTR,                             // a string, specifying the generated HTML
  							contentsTreeItems:contentsTreeItemsARRAY, // a nested array representing the contents tree
  							metaData:metaDataOBJ                      // an object, containing meta data properties
  						}
  						.............................................................................................
  
  					sectionsToSort
  						An array, containing the names of sections whose subsections should be sorted.
  					urlDictionary
  						An optional object, providing a dictionary of link text to URL mappings
  				*/
  				function _defaultedStringParam (_paramName,_defaultValue) {
  					var _paramValue = _params [_paramName];
  					return (_params [_paramName] = typeof _paramValue == _string ? _paramValue : _defaultValue);
  				}
  				_params = Uize.copy (_params);
  				var
  					_data = _params.data,
  					_urlDictionary = Uize.copyInto (Uize.lookup (_undefined,0,true),_params.urlDictionary),
  					_pathToRoot = _params.pathToRoot || '',
  					_indentChars = _defaultedStringParam ('indentChars','\t'),
  					_headingNumberingSeparator = _defaultedStringParam ('headingNumberingSeparator','. '),
  					_headingNumberingDelimiter = _defaultedStringParam ('headingNumberingDelimiter','.'),
  					_maxCssClassLevel = Uize.defaultNully (_params.maxCssClassLevel,9),
  					_sectionPath = [],
  					_levelListItemNos = [0],
  					_docLines = [],
  					_contentsTree = {items:[]},
  					_metaData = {},
  					_objectTemplates = Uize.copy (_builtInObjectTemplates,_params.objectTemplates)
  				;
  				if (typeof _data == _string)
  					_data = Uize.Data.Simple.parse ({simple:_data,parseName:false,ignoreWhitespaceLines:true})
  				;
  
  				/*** support for canonicalizing peer sections of the same name ***/
  					function _canonicalizePeerSections (_data) {
  						var _children = _data.children;
  						if (_children.length) {
  							/*** collapse all same-named sections at this level ***/
  								/* TODO:
  									- must support section titles possibly containing aliases
  									- section titles with the same display name but different aliases should be merged so that a single title exists with the union of all the aliases
  								*/
  								var _sectionsByTitle = Uize.lookup (_undefined,0,true); // safe empty lookup object
  								for (var _childNo = -1; ++_childNo < _children.length;) {
  									var
  										_child = _children [_childNo],
  										_childChildren = _child.children
  									;
  									if (_childChildren.length) {
  										var
  											_childSectionTitle = _child.value,
  											_existingSectionOfSameName = _sectionsByTitle [_childSectionTitle]
  										;
  										if (_existingSectionOfSameName) {
  											_existingSectionOfSameName.children =
  												_existingSectionOfSameName.children.concat (_childChildren)
  											;
  											_children.splice (_childNo,1);
  											_childNo--;
  										} else {
  											_sectionsByTitle [_childSectionTitle] = _child;
  										}
  									}
  								}
  
  							/*** perform canonicalizing within each of the peer sections ***/
  								Uize.forEach (_children,_canonicalizePeerSections,true);
  						}
  					}
  					_params.canonicalizePeerSections !== false &&
  						_canonicalizePeerSections (_data)
  					;
  
  				/*** support for sorting of peer sections ***/
  					var _sectionsToSort = _params.sectionsToSort;
  					if (_sectionsToSort) {
  						var
  							_sectionsToSortLookup = Uize.lookup (_sectionsToSort),
  							_sortPeerSections = function (_data) {
  								var _children = _data.children;
  								if (_children.length) {
  									/*** sort all the peer sections (if this section should be sorted) ***/
  										_sectionsToSortLookup [_data.value] && Uize.Array.Sort.sortBy (_children,'value.value');
  
  									/*** handle sorting within each of the peer sections ***/
  										Uize.forEach (_children,_sortPeerSections,true);
  								}
  							}
  						;
  						_sortPeerSections (_data);
  					}
  
  				/*** support code for intra-document section links ***/
  					// populate lookups with all section titles from all levels
  					var
  						_allSectionTitles = Uize.lookup (_undefined,0,true),
  						_allSectionTitlesLowerCase = Uize.lookup (_undefined,0,true),
  						_sectionNoByLevel = [0]
  					;
  					function _getSectionIdFromLookup (_lookup,_sectionTitle,_localSectionPath) {
  						var _sectionId = _lookup [_sectionTitle];
  						if (_sectionId) {
  							var
  								_sectionIds = _sectionId,
  								_sectionIdsLength = _sectionIds.length
  							;
  							_sectionId = _sectionIds [0];
  
  							/*** if more than one section of same name, then must find closest one in the document ***/
  								if (_localSectionPath && _sectionIdsLength > 1) {
  									var
  										_closestSectionId,
  										_closestSectionPath
  									;
  									for (var _sectionIdNo = -1, _sectionIsCloser; ++_sectionIdNo < _sectionIdsLength;) {
  										var _sectionPath = _getSectionPathFromId (_sectionId = _sectionIds [_sectionIdNo]);
  										if (!(_sectionIsCloser = !_closestSectionId)) {
  											/* NOTE:
  												Iterate through all the sections that share the same title, finding the section whose path is closest, in the document's structure, to the specified local section path.
  
  												For every level of the path of a section being considered, the distance between the section (at that level of the path) and the local section (at that level of the path) is compared to the distance between the currently closest section (at that level of the path) and the local section (at that level of the path).
  
  												If the section being considered is closer (at that level of the path), then it replaces the closest section. If it is more distant (at that level of the path), then no more levels of the section's path are examined. If it as at the same distance (at that level of the path), then further levels of the section's path are examined in order to either establish that the section is closer, or that it is more distant.
  											*/
  											for (
  												var _levelNo = -1, _sectionPathLength = _sectionPath.length;
  												++_levelNo < _sectionPathLength;
  											) {
  												var _levelDeltaBetweenNewAbsDistanceAndClosestAbsDistance =
  													Math.abs (_sectionPath [_levelNo] - (_localSectionPath [_levelNo] || 0)) -
  													Math.abs (
  														(_closestSectionPath [_levelNo] || 0) - (_localSectionPath [_levelNo] || 0)
  													)
  												;
  												if (_levelDeltaBetweenNewAbsDistanceAndClosestAbsDistance < 0) {
  													_sectionIsCloser = true;
  													break;
  												} else if (_levelDeltaBetweenNewAbsDistanceAndClosestAbsDistance > 0) {
  													_sectionIsCloser = false;
  													break;
  												}
  											}
  										}
  										if (_sectionIsCloser) {
  											_closestSectionId = _sectionId;
  											_closestSectionPath = _sectionPath;
  										}
  									}
  									_sectionId = _closestSectionId;
  								}
  						}
  						return _sectionId;
  					}
  					function _buildAllSectionTitles (_data,_level,_parentSectionId) {
  						/* TO DO:
  							Ultimately, for improved disambiguation, this code should handle multiple sections at different places in the document tree sharing the same name. To this end, each entry in _allSectionTitles may need to be an array of one or more section profiles. A disambiguation algorithm can then handle cases where a single title is mapped to multiple sections, finding the section that is closest to the section containing the link.
  						*/
  						var _children = _data.children;
  						if (_children.length) {
  							_sectionNoByLevel [_level]++;
  							var _sectionId = _level
  								? _parentSectionId + (_parentSectionId && '_') + _sectionNoByLevel [_level]
  								: ''
  							;
  							/*** add section aliases (and lower case versions) to lookup for intra-document linking ***/
  								for (
  									var
  										_sectionAliasNo = -1,
  										_sectionAliases = (_data.value + '').split (_sectionAliasesRegExp),
  										_sectionAliasesLength = _sectionAliases.length,
  										_sectionAlias,
  										_sectionAliasLowerCase
  									;
  									++_sectionAliasNo < _sectionAliasesLength;
  								) {
  									(
  										_allSectionTitles [_sectionAlias = _sectionAliases [_sectionAliasNo]] ||
  										(_allSectionTitles [_sectionAlias] = [])
  									).push (
  										_sectionId
  									);
  									(
  										_allSectionTitlesLowerCase [_sectionAliasLowerCase = _sectionAlias.toLowerCase ()] ||
  										(_allSectionTitlesLowerCase [_sectionAliasLowerCase] = [])
  									).push (
  										_sectionId
  									);
  								}
  
  							/*** build section titles for deeper levels ***/
  								_sectionNoByLevel [_level + 1] = 0;
  								for (var _childNo = -1, _childrenLength = _children.length; ++_childNo < _childrenLength;)
  									_buildAllSectionTitles (_children [_childNo],_level + 1,_sectionId)
  								;
  						}
  					}
  					_buildAllSectionTitles (_data,0,'');
  
  				function _translateInlineFormatting (_line,_sectionPath) {
  					function _format (_formattingPrefix,_text,_formattingSuffix,_linkType,_link) {
  						if (!_sectionPath) return _text;
  
  						var _linkTypeIsUrl = _linkType == 'url';
  						if (_linkType && !_linkTypeIsUrl) {
  							if (_linkType == 'text') _link = _text;
  							var _sectionId =
  								_getSectionIdFromLookup (_allSectionTitles,_link,_sectionPath) ||
  								_getSectionIdFromLookup (_allSectionTitlesLowerCase,_link.toLowerCase (),_sectionPath)
  							;
  							_sectionId
  								? (_link = '#' + _sectionId)
  								: ((_link = _urlDictionary [_link] || '') && (_linkTypeIsUrl = true))
  							;
  						}
  						if (_slashCharCodesMap [_link.charCodeAt (0)])
  							_link = _pathToRoot + _link.slice (1)
  						;
  						return (
  							_formattingPrefix +
  							(
  								_link
  									? (
  										'<a href="' + _link + '"' +
  											(
  												_linkTypeIsUrl && /^[a-zA-Z]+:/.test (_link)
  													? ' target="_blank" class="externalSiteLink"'
  													: ''
  											) +
  										'>' + _text + '</a>'
  									)
  									: _text
  							) +
  							_formattingSuffix
  						);
  					}
  					return (
  						_line.replace (
  							/^#(\S*)/,
  							function (_match,_anchorName) {return _format ('<a name="' + _anchorName + '">','','</a>')}
  							/* support for anchors, of the form...
  								#anchorName
  							*/
  						).replace (
  							/\B\*.+?\*\B/g,
  							function (_match) {return _format ('<b>',_match.slice (1,-1),'</b>','text')}
  							/* support for bolding, of the form...
  								This is some *bolded text*, and here is some more *bolded text*.
  							*/
  						).replace (
  							/\b__.+?__\b/g,
  							function (_match) {return _format ('<b><i>',_match.slice (2,-2),'</i></b>','text')}
  							/* support for bolded italics, of the form...
  								Here's some __bolded italics__, and here's more __bolded italics__.
  							*/
  						).replace (
  							/\b_.+?_\b/g,
  							function (_match) {return _format ('<i>',_match.slice (1,-1),'</i>','text')}
  							/* support for italics, of the form...
  								Here's some _italics_, and here's more _italics_.
  							*/
  						).replace (
  							/\B==.+?==\B/g,
  							function (_match) {return _format ('<code><b>',_match.slice (2,-2),'</b></code>','text')}
  							/* support for bolded inline code, of the form...
  								Here's some ==bolded inline code==. Ain't it purrrdy?
  							*/
  						).replace (
  							/\B=.+?=\B/g,
  							function (_match) {return _format ('<code>',_match.slice (1,-1),'</code>','text')}
  							/* support for inline code, of the form...
  								Here's some =inline code=. Ain't it purrrdy?
  							*/
  						).replace (
  							/\B`.+?`\B/g,
  							function (_match) {return _format ('',_match.slice (1,-1),'','text')}
  							/* support for intra-document links to sections, of the form...
  								See the `Mathematical Progressions` section for further details.
  							*/
  						).replace (
  							/\[\[(#.+?|[a-zA-Z]+:.+?|.+?\.(?:htm|html|jpg|gif|png)(?:[\?#][^\]]*)?)\]\[(.+?)\]\]/g,
  							function (_match,_linkHref,_linkText) {return _format ('',_linkText,'','url',_linkHref)}
  							/* support for links, of the form...
  								Visit [[http://www.tomkidding.com][Tom Kidding's Web site]]
  								for further info, consult [[resume.html][Tom Kidding's Resume]]
  							*/
  						).replace (
  							/\[\[(.+?)\]\[(.+?)\]\]/g,
  							function (_match,_wikiWord,_linkText) {return _format ('',_linkText,'','section',_wikiWord)}
  							/* support for intra-document links to sections, of the form...
  								[[Mathematical Progressions][see the Mathematical Progressions section]] for further details
  							*/
  						).replace (
  							/\[\[(#.+?|[a-zA-Z]+?:.+?)\]\]/g,
  							function (_match,_linkHref) {return _format ('',_linkHref,'','url',_linkHref)}
  							/* support for links, of the form...
  								Visit [[http://www.tomkidding.com]]
  							*/
  						).replace (
  							/\[\[(.+?)\]\]/g,
  							function (_match,_wikiWord) {return _format ('',_wikiWord,'','text')}
  							/* support for intra-document links to sections, of the form...
  								See the [[Mathematical Progressions]] section for further details.
  							*/
  						)
  					);
  				}
  				function _addDocLinesFromData (
  					_data,_level,_parentContentsItem,_indentStr,_parentHeadingPath,_parentHeadingDisplayPrefix
  				) {
  					function _addDocLine (_docLine,_indent) {
  						_docLines.push ((_indent !== false ? _indentStr : '') + _docLine);
  					}
  					function _closeListIfNeeded (_isNextLevel) {
  						var _levelForList = _level + !!_isNextLevel;
  						if (_levelListItemNos [_levelForList]) {
  							_addDocLine ((_isNextLevel ? _indentChars : '') + '</table>');
  							_levelListItemNos [_levelForList] = 0;
  						}
  					}
  					var
  						_children = _data.children,
  						_value = _data.value,
  						_listItemPrefixMatch
  					;
  					if (!_children.length) {
  						if (/\r|\n|\r\n/.test (_value)) {
  							/*** support for sample code blocks and arbitrary objects ***/
  							var _objectHtml;
  							_closeListIfNeeded ();
  
  							/*** determine if block is arbitrary object, or just plain sample code block ***/
  								var
  									_objectTemplate,
  									_objectParams,
  									_objectTypeMatch = _value.match (_objectTypeRegExp)
  								;
  								if (_objectTypeMatch) {
  									var
  										_objectType = _objectTypeMatch [1].toLowerCase (),
  										_objectTypeIsMetaData = _objectType == 'metadata'
  									;
  									if (_objectTypeIsMetaData || (_objectTemplate = _objectTemplates [_objectType])) {
  										var _objectParamsStr = _value.slice (_objectTypeMatch [0].length);
  										_objectParams = _objectParamsIsJsonRegExp.test (_objectParamsStr)
  											? Uize.Json.from (_objectParamsStr)
  											: Uize.Data.Simple.parse ({
  												simple:_objectParamsStr,
  												collapseChildren:true,
  												ignoreWhitespaceLines:true
  											})
  										;
  										_objectTypeIsMetaData && Uize.copyInto (_metaData,_objectParams);
  									}
  								} else {
  									_objectTemplate = _objectTemplates.samplecode;
  									_objectParams = {code:_value};
  								}
  								if (_objectTemplate)
  									_objectHtml = _objectTemplate (_objectParams,_indentStr,_indentChars,_params)
  								;
  
  							if (_objectHtml != _undefined) {
  								_addDocLine ('');
  								_addDocLine (_objectHtml,false);
  								_addDocLine ('');
  							}
  						} else if (/^={3,}$/.test (_value)) {
  							/*** support for thick horizontal rule ***/
  							_closeListIfNeeded ();
  							_addDocLine ('<hr class="thick"/>');
  						} else if (/^-{3,}$/.test (_value)) {
  							/*** support for thin horizontal rule ***/
  							_closeListIfNeeded ();
  							_addDocLine ('<hr class="thin"/>');
  						} else if (
  							(_listItemPrefixMatch = _value.match (_listItemPrefixRegExp)) &&
  							/[^\w\s\d]/.test (_listItemPrefixMatch [1])
  						) {
  							/* support for lists
  								- bullet lists (unordered, decorated with a bullet character)
  									- this is a list item
  									* this is a list item
  									~ this is a list item
  									: this is a list item
  									. this is a list item
  
  								- ordered lists
  									@ this is a list item
  									# this is a list item
  									+ this is a list item
  
  								[@] this is a list item
  								[a] this is a list item
  								[A] this is a list item
  								[1] this is a list item
  
  								(@) this is a list item
  								(a) this is a list item
  								(A) this is a list item
  								(1) this is a list item
  
  								{@} this is a list item
  								{a} this is a list item
  								{A} this is a list item
  								{1} this is a list item
  
  								<@> this is a list item
  								<a> this is a list item
  								<A> this is a list item
  								<1> this is a list item
  
  								<< @ >> this is a list item
  								<< a >> this is a list item
  								<< A >> this is a list item
  								<< 1 >> this is a list item
  
  								@) this is a list item
  								a) this is a list item
  								A) this is a list item
  								1) this is a list item
  
  								@] this is a list item
  								a] this is a list item
  								A] this is a list item
  								1] this is a list item
  
  								@> this is a list item
  								a> this is a list item
  								A> this is a list item
  								1> this is a list item
  
  								@ - this is a list item
  								a - this is a list item
  								A - this is a list item
  								1 - this is a list item
  
  								@. this is a list item
  								a. this is a list item
  								A. this is a list item
  								1. this is a list item
  
  								@: this is a list item
  								a: this is a list item
  								A: this is a list item
  								1: this is a list item
  							*/
  							var
  								_listItemPrefix = _listItemPrefixMatch [1],
  								_orderingStyleMatch = _listItemPrefix.match (_orderingStyleRegExp)
  							;
  							_levelListItemNos [_level] ||
  								_addDocLine ('<table class="list">')
  							;
  							if (_orderingStyleMatch) {
  								var
  									_orderingStyle = _orderingStyleMatch [1],
  									_orderingStr = ''
  								;
  								if (/[#\+]|\d+/.test (_orderingStyle)) {
  									_orderingStr = _levelListItemNos [_level] + 1 + '';
  								} else if (/[@a-z]/i.test (_orderingStyle)) {
  									_orderingStr = 'abcdefghijklmnopqrstuvwxyz'.charAt (_levelListItemNos [_level]);
  									if (/[A-Z]/.test (_orderingStyle))
  										_orderingStr = _orderingStr.toUpperCase ()
  									;
  								}
  								_listItemPrefix = _listItemPrefix.replace (_orderingStyleRegExp,_orderingStr) + '&nbsp;';
  							} else {
  								_listItemPrefix = _onlyBulletCharRegExp.test (_listItemPrefix)
  									? _listItemPrefix.replace (_bulletCharRegExp,'<span class="bullet"></span>')
  									: _toSampleCode (_listItemPrefix) + '&nbsp;'
  								;
  							}
  							_addDocLine (
  								'<tr valign="top">' +
  									'<td style="white-space:nowrap;">' + _listItemPrefix + '</td>' +
  									'<td>' +
  										_translateInlineFormatting (_value.replace (_listItemPrefixRegExp,''),_sectionPath) +
  									'</td>' +
  								'</tr>'
  							);
  							_levelListItemNos [_level]++;
  						} else {
  							/*** support for paragraph ***/
  							_closeListIfNeeded ();
  							var _paragraph = _translateInlineFormatting (_value,_sectionPath);
  							if (/[A-Z]/.test (_paragraph) && !/[a-z]/.test (_paragraph))
  								_paragraph = '<span class="allCaps">' + _paragraph + '</span>'
  							;
  							_addDocLine ('<p>' + _paragraph + '</p>');
  							_addDocLine ('');
  						}
  					} else {
  						_closeListIfNeeded ();
  						_sectionPath [_level - 1]++;
  						var
  							_aliasDelimiterPos = _value.search (_sectionAliasesRegExp),
  							_headingSansAliases = _aliasDelimiterPos > -1 ? _value.slice (0,_aliasDelimiterPos) : _value,
  							_cssClassLevel = Math.min (_level,_maxCssClassLevel),
  							_hasNumbering = _level > 0 && true /* TO DO: add switch for numbering at some point */,
  							_headingPrefix = _hasNumbering ? _sectionPath.join ('_') : '',
  							_headingTitle =
  								(
  									_sectionPath.length
  										? _sectionPath.join (_headingNumberingDelimiter) + _headingNumberingSeparator
  										: ''
  								) + _headingSansAliases,
  							_headingPath = (_parentHeadingPath ? (_parentHeadingPath + ' -> ') : '') + _headingTitle,
  							_headingPathAsTitleAttribute = ' title="' + _htmlEncode (_headingPath) + '"',
  							_headingDisplayPrefix = _hasNumbering
  								? (
  									(
  										_parentHeadingDisplayPrefix
  											? (_parentHeadingDisplayPrefix + _headingNumberingDelimiter)
  											: ''
  									) +
  									'<a href="#' + _headingPrefix + '"' + _headingPathAsTitleAttribute + '>' +
  										_sectionPath [_level - 1] +
  									'</a>'
  								)
  								: '',
  							_contentsItem = {
  								title:_headingTitle || 'Contents',
  								description:
  									_children [0].children.length
  										? ''
  										: _limitLength (_translateInlineFormatting (_children [0].value),400),
  								link:_headingPrefix ? ('#' + _headingPrefix) : '',
  								items:[]
  							}
  						;
  						_parentContentsItem.items.push (_contentsItem);
  						if (_value) {
  							var
  								_hTag = 'h' + Math.min (_level,5),
  								_headingNumber = _headingDisplayPrefix + _headingNumberingSeparator
  							;
  							_addDocLine ('<a name="' + _headingPrefix + '"></a>');
  							_addDocLine (
  								'<' + _hTag + ' class="heading' + _cssClassLevel + '"' + _headingPathAsTitleAttribute + '>' +
  									(
  										_headingDisplayPrefix
  											? '<span class="headingNumber">' + _headingNumber + '</span>'
  											: ''
  									) +
  									_headingSansAliases +
  								'</' + _hTag + '>'
  							);
  						}
  						_addDocLine ('<div class="contents' + _cssClassLevel + '">');
  						_sectionPath [_level] = _levelListItemNos [_level + 1] = 0;
  						for (var _childNo = -1, _childrenLength = _children.length; ++_childNo < _childrenLength;)
  							_addDocLinesFromData (
  								_children [_childNo],
  								_level + 1,
  								_contentsItem,
  								_indentStr + _indentChars,
  								_headingPath,
  								_headingDisplayPrefix
  							)
  						;
  						_closeListIfNeeded (true);
  						/\S/.test (_docLines [_docLines.length - 1]) || _docLines.pop ();
  						_addDocLine ('</div>');
  						_addDocLine ('');
  						_sectionPath.length = _level;
  					}
  				}
  				_addDocLinesFromData (_data,0,_contentsTree,'','','');
  				var
  					_contentsTreeItems = _contentsTree.items,
  					_html = (
  						_params.contentsList !== false &&
  						(
  							/* NOTE:
  								content tree must have some root items, and must either have more than one root item, or the single root item must have at least one child item
  							*/
  							_contentsTreeItems.length &&
  							(_contentsTreeItems.length > 1 || _contentsTreeItems [0].items.length)
  						)
  							? (
  								'<div id="page-contents" class="contents-tree">\n' +
  									Uize.Templates.List.process ({items:_contentsTreeItems}) + '\n' +
  								'</div>\n' +
  								'\n'
  							)
  							: ''
  					) + _docLines.join ('\n')
  				;
  				return (
  					_params.result == 'full'
  						? {
  							html:_html,
  							contentsTreeItems:_contentsTreeItems,
  							metaData:_metaData
  						}
  						: _html
  				);
  			}
  
  			function _toDocument (_simple,_simpleDocParams) {
  				return _build (Uize.copyInto ({data:_simple},_simpleDocParams));
  			}
  
  			function _toSampleCode (_sourceStr) {
  				return _sourceStr.replace (/\t/g,'  ').replace (/&/g,'&amp;').replace (/</g,'&lt;').replace (/>/g,'&gt;');
  			}
  
  		return Uize.package ({
  			build:_build,
  			toDocument:_toDocument,
  			toSampleCode:_toSampleCode
  		});
  	}
  });
  
  