Skip to content

Instantly share code, notes, and snippets.

@trevordevore
Last active October 1, 2015 02:37
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trevordevore/1903979 to your computer and use it in GitHub Desktop.
Save trevordevore/1903979 to your computer and use it in GitHub Desktop.
Convert LiveCode styledText array to/from XHTML
/**
* \brief Converts a styled text array to XHTML.
*
* \param pStyledTextA The array to convert.
*
* \return XHTML
*/
function ConvertStyledTextToXHTML pStyledTextA
local theXHTML, theRun, theString
local theListKey
local theClosingListTag, theParaClasses, checkForIndent, theIndentLevel
set the wholematches to true
repeat with i = 1 to the number of elements of pStyledTextA
if pStyledTextA[i] is not an array then next repeat
## paragraph level formatting stored in pStyledTextA[i]["style"]
## textAlign, listStyle, listDepth, listIndent, firstIndent, leftIndent, rightIndent,
## spaceAbove, spaceBelow, tabStops, backgroundColor, borderWidth, borderColor,
## hGrid, vGrid, dontWrap and padding.
## todo ...
##########
# Determine paragraph tag
##########
put DecodeMetaDataArray(pStyledTextA[i]["metadata"]) into theMetaDataA
put theMetaDataA["style"] into theParaStyle
switch theParaStyle
case "code"
put "pre" into theParaTag
break
default
if pStyledTextA[i]["style"]["listStyle"] is not empty then
##########
# NOTE: This code does not support 'skip'.
# <ul>
# <li>Item
# <ol>
# <li>Sub item
# </ol>
# </li>
# </ul>
##########
# Question 1) Are we are at same level and same depth?
# Yes: Do nothing
# No: Question 2
# Question 2) Is the level increasing?
# Yes: Open new list (ul/ol).
# No: Do nothing. Already open.
# 1)
if pStyledTextA[i]["style"]["listStyle"] is not theParaListsA[the number of elements of theParaListsA]["listStyle"] \
OR pStyledTextA[i]["style"]["listDepth"] is not theParaListsA[the number of elements of theParaListsA]["listDepth"] then
switch pStyledTextA[i]["style"]["listStyle"]
case "disc"
case "circle"
case "square"
put "ul" into theListTag
break
default
put "ol" into theListTag
break
end switch
# 2)
if pStyledTextA[i]["style"]["listDepth"] > theParaListsA[the number of elements of theParaListsA]["listDepth"] then
put "<" & theListTag & ">" after theXHTML
end if
# add to nested list
put the number of elements of theParaListsA + 1 into theCounter
put theListTag into theParaListsA[theCounter]["tag"]
put pStyledTextA[i]["style"]["listStyle"] into theParaListsA[theCounter]["listStyle"]
put pStyledTextA[i]["style"]["listDepth"] into theParaListsA[theCounter]["listDepth"]
end if
put "li" into theParaTag
else
put "p" into theParaTag
end if
end switch
put _DetermineXHTMLClassesForParagraph(pStyledTextA, i) into theParaClasses
put "<" & theParaTag after theXHTML
if pStyledTextA[i]["style"]["listIndex"] is not empty then
put " value=" & quote & pStyledTextA[i]["style"]["listIndex"] & quote after theXHTML
end if
if theParaClasses is not empty then
replace cr with space in theParaClasses
put " class=" & quote & theParaClasses & quote after theXHTML
end if
put ">" after theXHTML
put empty into theRun
put empty into theString
##########
# Add text runs to paragraph
##########
repeat with j = 1 to the number of elements of pStyledTextA[i]["runs"]
if pStyledTextA[i]["runs"][j] is not an array then next repeat
put empty into theStyles
## style: textFont, textSize, textStyle, textColor, backgroundColor, linkText, imageSource
-- pStyledTextA[i]["runs"][j]["style"]
-- pStyledTextA[i]["runs"][j]["metadata"]
-- pStyledTextA[i]["runs"][j]["text"]
-- pStyledTextA[i]["runs"][j]["unicodetext"]
# Normalize text run: UTF8
if "unicodetext" is among the keys of pStyledTextA[i]["runs"][j] then
put unidecode(pStyledTextA[i]["runs"][j]["unicodetext"], "utf8") into theRun
else
put unidecode(uniencode(pStyledTextA[i]["runs"][j]["text"]), "utf8") into theRun
end if
put _CleanseNonPrintingCharacters(theRun) into theRun
put _EscapePredefinedXMLEntities(theRun) into theRun
##########
## Get meta data for rest of operations.
##########
put DecodeMetaDataArray(pStyledTextA[i]["runs"][j]["metadata"]) into theMetaDataA
# Modify for "code" style, etc.
_UpdateTextBasedOnStyle theParaStyle, theMetaDataA["style"], theRun
##########
## Define Styles
##########
if pStyledTextA[i]["runs"][j]["style"]["textColor"] is not empty then
put "color: rgb(" & pStyledTextA[i]["runs"][j]["style"]["textColor"] & ")" into line (the number of lines of theStyles + 1) of theStyles
end if
if "underline" is among the items of pStyledTextA[i]["runs"][j]["style"]["textStyle"] then
put "text-decoration:underline" into line (the number of lines of theStyles + 1) of theStyles
end if
##########
## Add in tags and links
##########
if pStyledTextA[i]["runs"][j]["style"]["linkText"] is not empty then
## this is how I stored target info for links
## Ensure that "&" in query string is converted to "&amp;"
put TextToUTF8(pStyledTextA[i]["runs"][j]["style"]["linkText"]) into pStyledTextA[i]["runs"][j]["style"]["linkText"]
put _EscapePredefinedXMLEntities(pStyledTextA[i]["runs"][j]["style"]["linkText"]) into pStyledTextA[i]["runs"][j]["style"]["linkText"]
put "<a href=" & quote & pStyledTextA[i]["runs"][j]["style"]["linkText"] & quote into theLink
repeat for each key theKey in theMetaDataA
if theKey is "href target" then put "target" into theAttr
else put theKey into theAttr
put space & theAttr & "=" & quote & _EscapePredefinedXMLEntities(theMetaDataA[theKey]) & quote after theLink
end repeat
put ">" after theLink
put theLink before theRun
put "</a>" after theRun
end if
if pStyledTextA[i]["runs"][j]["style"]["textShift"] is an integer then
if pStyledTextA[i]["runs"][j]["style"]["textShift"] < 0 then
put "<sup>" before theRun
put "</sup>" after theRun
else if pStyledTextA[i]["runs"][j]["style"]["textShift"] > 0 then
put "<sub>" before theRun
put "</sub>" after theRun
end if
end if
if "bold" is among the items of pStyledTextA[i]["runs"][j]["style"]["textStyle"] then
put "<strong>" before theRun
put "</strong>" after theRun
end if
if "italic" is among the items of pStyledTextA[i]["runs"][j]["style"]["textStyle"] then
put "<em>" before theRun
put "</em>" after theRun
end if
##########
## Add in spans for styles
##########
if theStyles is not empty then
replace cr with ";" in theStyles
## Since each line will get a new <p> tag then we need to apply span to each line.
put "<span style=" & quote & theStyles & quote & ">" before theRun
put "</span>" after theRun
end if
put theRun after theString
end repeat # Run
## Append new string
put theString after theXHTML
# Close out the paragraph
put "</" & theParaTag & ">" & cr after theXHTML
##########
# Is listStyle changing/ending in next paragraph? Close out the list (ul/ol).
##########
if theParaListsA is an array then
# Question 1: are we at last paragraph?
# Yes: Close all open list paragraphs
# Question 2: Is depth decreasing in next paragraph or is depth same but style different?
# Yes: Close paragraph and then check again. We may be closing out multiple lists.
# No: Don't close paragraph.
if pStyledTextA[i+1] is not an array then
# 1)
repeat with theIndex = the number of elements of theParaListsA down to 1
put "</" & theParaListsA[theIndex]["tag"] & ">" & cr after theXHTML
delete local theParaListsA[theIndex]
end repeat
else
# 2)
repeat with theIndex = the number of elements of theParaListsA down to 1
if pStyledTextA[i+1]["style"]["listDepth"] < theParaListsA[theIndex]["listDepth"] \
OR (pStyledTextA[i+1]["style"]["listDepth"] is theParaListsA[theIndex]["listDepth"] AND \
pStyledTextA[i+1]["style"]["listStyle"] is not theParaListsA[theIndex]["listStyle"]) then
put "</" & theParaListsA[theIndex]["tag"] & ">" & cr after theXHTML
delete local theParaListsA[theIndex]
else
exit repeat
end if
end repeat
end if
end if
end repeat # paragraph
if the last char of theXHTML is cr then delete the last char of theXHTML
## Livecode has a run for empty paragraphs but XHTML adds spacing automatically.
## Get rid of those empty paragraphs.
-- replace "</ul><p></p><ul>" with "</ul><ul>" in theXHTML
-- replace "</ul><p></p><p>" with "</ul><p>" in theXHTML
-- replace "</p><p></p><ul>" with "</p><ul>" in theXHTML
-- replace "</p><p></p><p>" with "</p><p>" in theXHTML
return theXHTML
end ConvertStyledTextToXHTML
/**
* |brief Inspects a paragraph and determines the XHTML classes to apply to it.
*
* \param @pStyledTextA the text run.
* \param pParaIndex The paragraph to inspect.
*
* \seealso ConvertStyledTextToXHTML
*
* \return String of classes, one per line.
*/
private function _DetermineXHTMLClassesForParagraph @pStyledTextA, pParaIndex
if pStyledTextA[pParaIndex]["runs"] is not an array then return empty
local theParaClasses
local checkForIndent = "true"
local theIndentLevel = 0
repeat with i = 1 to the number of elements of pStyledTextA[pParaIndex]["runs"]
# Normalize text so we can inspect.
if "unicodetext" is among the keys of pStyledTextA[pParaIndex]["runs"][i] then
put unidecode(pStyledTextA[pParaIndex]["runs"][i]["unicodetext"], "utf8") into theRun
else
put unidecode(uniencode(pStyledTextA[pParaIndex]["runs"][i]["text"]), "utf8") into theRun
end if
# Look for tabs at start of line. We add a style for indenting: indent1, indent2, etc.
if checkForIndent then
repeat for each char theChar in theRun
if theChar is tab then
add 1 to theIndentLevel
else
put false into checkForIndent
exit repeat
end if
end repeat
end if
end repeat # Run
# add tab indents to class
if theIndentLevel > 0 then
put "indent" & theIndentLevel into line (the number of lines of theParaClasses + 1) of theParaClasses
end if
return theParaClasses
end _DetermineXHTMLClassesForParagraph
/**
* |brief Makes any changes to a run based on the paragraph and run style.
*
* \param pParaStyle The style of the paragraph the run is in.
* \param pRunStyle The style of the run.
* \param @pText The text to modify.
*
* \return empty
*/
private command _UpdateTextBasedOnStyle pParaStyle, pRunStyle, @pText
if pParaStyle is "code" OR pRunStyle is "code" then
replace numToChar(11) with cr in pText
else
replace numToChar(11) with "<br />" in pText
end if
return empty
end _UpdateTextBasedOnStyle
local sStyledTextA, sStyledTextIndexPathA
local sXMLTreeStateA
/**
* \brief Converts XHTML to a styled text array.
*
* \param pXHTML The XHTML to convert.
*
* \return XHTML
*/
function ConvertXHTMLtoStyledText pXHTML
local theError, theStyledTextA
if pXHTML is not empty then
## Strip returns existing after tags.
## This keeps unwanted revStartXMLData messages from firing.
## No effort made to strip other white space between tags. This type of
## white space will fire off unwated revStartXMLData messages so beware.
replace ">" & crlf with ">" in pXHTML
replace ">" & cr with ">" in pXHTML
replace ">" & lf with ">" in pXHTML
## Initialize some variables
put empty into sXMLTreeStateA["run"]["textStyle"]
put empty into sXMLTreeStateA["previous run"]["textStyle"]
put qstr("<?xml version=`1.0` encoding=`UTF-8` ?>") into theHeader
put revCreateXMLTree(theHeader & cr & "<body>" & pXHTML & "</body>", false, false, true) into theError
put item 2 to -1 of theError into theError ## Ditches any numbers of revxmlerr, prefixes.
put sStyledTextA into theStyledTextA
put empty into sStyledTextA
end if
if theError is empty then
return theStyledTextA
else
return theError
end if
end ConvertXHTMLtoStyledText
on revXMLStartTree
put empty into sStyledTextA
end revXMLStartTree
/**
* \brief
*
* \param pNodeName The name of the node being parsed.
* \param pNodeAttributes One attribute per line. Each attribute name is separated from value by comma.
*
*/
on revStartXMLNode pNodeName, pNodeAttributes
local theParaIndex
put pNodeName into line (the number of lines of sXMLTreeStateA["open node"] + 1) of sXMLTreeStateA["open node"]
split pNodeAttributes by cr and ","
put the number of elements of sStyledTextA into theParaIndex
switch pNodeName
case "pre"
case "p" ## Start a new paragraph entry
# TODO: <p> tags within <li> (LiveCode htmltext) are not handled properly.
## LiveCode likes an extra run to show paragraph spacing.
## Note: removed as we use spaceAbove now.
-- if sXMLTreeStateA["block is open"] then
-- add 1 to theParaIndex
-- put empty into sStyledTextA[theParaIndex]["runs"]
-- put false into sXMLTreeStateA["block is open"]
-- end if
# New paragraph: reset textStyle, textColor, etc.
repeat for each key theKey in sXMLTreeStateA["run"]
put empty into sXMLTreeStateA["run"][theKey]
end repeat
repeat for each key theKey in sXMLTreeStateA["previous run"]
put empty into sXMLTreeStateA["previous run"][theKey]
end repeat
add 1 to theParaIndex
put empty into sStyledTextA[theParaIndex]
if theParaIndex > 1 then
put 16 into sStyledTextA[theParaIndex]["style"]["spaceAbove"] ## trigger proper spacing
end if
switch pNodeName
case "pre"
put "code" into sStyledTextA[theParaIndex]["metadata"]["style"]
break
end switch
put StringToIndexPath(theParaIndex & ".runs.1") into sStyledTextIndexPathA
put empty into sStyledTextA[sStyledTextIndexPathA]["unicodetext"] # default value. If empty <p> tag all settings would be lost otherwise (i.e. spaceAbove).
break
case "ul"
add 1 to sXMLTreeStateA["list depth"]
put "disc" into sXMLTreeStateA["list type"][ sXMLTreeStateA["list depth"] ]
break
case "ol"
add 1 to sXMLTreeStateA["list depth"]
put "decimal" into sXMLTreeStateA["list type"][ sXMLTreeStateA["list depth"] ]
break
case "li"
# New line: reset textStyle, textColor, etc.
repeat for each key theKey in sXMLTreeStateA["run"]
put empty into sXMLTreeStateA["run"][theKey]
end repeat
repeat for each key theKey in sXMLTreeStateA["previous run"]
put empty into sXMLTreeStateA["previous run"][theKey]
end repeat
add 1 to theParaIndex
## trigger proper spacing for first line in list
if sStyledTextA[theParaIndex - 1]["style"]["listStyle"] is empty then
put 16 into sStyledTextA[theParaIndex]["style"]["spaceAbove"]
end if
put sXMLTreeStateA["list type"][ sXMLTreeStateA["list depth"] ] into sStyledTextA[theParaIndex]["style"]["listStyle"]
if pNodeAttributes["value"] is not empty then put pNodeAttributes["value"] into sStyledTextA[theParaIndex]["style"]["listIndex"]
put sXMLTreeStateA["list depth"] into sStyledTextA[theParaIndex]["style"]["listDepth"]
put StringToIndexPath(theParaIndex & ".runs." & the number of elements of sStyledTextA[theParaIndex]["runs"] + 1) into sStyledTextIndexPathA
break
case "span"
##########
## Strip whitespace
##########
-- text-decoration: underline; something-else: what
put pNodeAttributes["style"] into theStyles
set the itemDelimiter to ":"
repeat with theItemNo = 1 to the number of items of theStyles["style"]
put word 1 to -1 of item theItemNo of theStyles["style"] into item theItemNo of theStyles["style"]
end repeat
set the itemDelimiter to ";"
repeat with theItemNo = 1 to the number of items of theStyles["style"]
put word 1 to -1 of item theItemNo of theStyles["style"] into item theItemNo of theStyles["style"]
end repeat
set the itemDelimiter to ","
repeat with theItemNo = 1 to the number of items of theStyles["style"]
put word 1 to -1 of item theItemNo of theStyles["style"] into item theItemNo of theStyles["style"]
end repeat
set the wholematches to true
split theStyles by ";" and ":"
repeat for each key theKey in theStyles
put word 1 to -1 of theStyles[theKey] into theStyles[theKey]
switch theKey
case "text-decoration"
if "underline" is among the items of theStyles[theKey] then
put _AddToList("underline", sXMLTreeStateA["run"]["textStyle"]) into sXMLTreeStateA["run"]["textStyle"]
end if
break
case "color"
if theStyles[theKey] begins with "rgb" then
put _StripNonNumericListChars(theStyles[theKey]) into sXMLTreeStateA["run"]["textColor"]
else
put theStyles[theKey] into sXMLTreeStateA["run"]["textColor"]
end if
break
end switch
end repeat
break
case "a"
put _AddToList("link", sXMLTreeStateA["run"]["textStyle"]) into sXMLTreeStateA["run"]["textStyle"]
put pNodeAttributes["href"] into sXMLTreeStateA["run"]["linkText"]
replace "&#38;" with "&" in sXMLTreeStateA["run"]["linkText"] ## xml parser is converting &amp; to entity number.
repeat for each key theKey in pNodeAttributes
if theKey is "href" then next repeat
if theKey is "target" then put "href target" into theAttr
else put theKey into theAttr
put pNodeAttributes[theKey] into sXMLTreeStateA["run"]["metadata"][theAttr]
end repeat
break
case "sub"
put 4 into sXMLTreeStateA["run"]["textShift"]
break
case "sup"
put -4 into sXMLTreeStateA["run"]["textShift"]
break
case "b"
case "strong"
put _AddToList("bold", sXMLTreeStateA["run"]["textStyle"]) into sXMLTreeStateA["run"]["textStyle"]
break
case "i"
case "em"
put _AddToList("italic", sXMLTreeStateA["run"]["textStyle"]) into sXMLTreeStateA["run"]["textStyle"]
break
case "br"
put uniencode(numToChar(11)) after sStyledTextA[sStyledTextIndexPathA]["unicodetext"]
break
end switch
end revStartXMLNode
/**
* \brief Sent when a node has finished being processed.
*
*/
on revEndXMLNode pNodeName
## Remove style from list of active styles.
switch pNodeName
case "a"
put _RemoveFromList("link", sXMLTreeStateA["run"]["textStyle"]) into sXMLTreeStateA["run"]["textStyle"]
put empty into sXMLTreeStateA["run"]["linkText"]
delete local sXMLTreeStateA["run"]["metadata"]["href target"]
break
case "sub"
case "sup"
put empty into sXMLTreeStateA["run"]["textShift"]
break
case "b"
case "strong"
put _RemoveFromList("bold", sXMLTreeStateA["run"]["textStyle"]) into sXMLTreeStateA["run"]["textStyle"]
break
case "i"
case "em"
put _RemoveFromList("italic", sXMLTreeStateA["run"]["textStyle"]) into sXMLTreeStateA["run"]["textStyle"]
break
case "span"
put _RemoveFromList("underline", sXMLTreeStateA["run"]["textStyle"]) into sXMLTreeStateA["run"]["textStyle"]
put empty into sXMLTreeStateA["run"]["textColor"]
break
case "ul"
case "ol"
subtract 1 from sXMLTreeStateA["list depth"]
break
case "p"
case "pre"
case "li"
# encode metadata
put the number of elements of sStyledTextA into theParaIndex
if sStyledTextA[theParaIndex]["metadata"] is an array then
put EncodeMetaDataArray(sStyledTextA[theParaIndex]["metadata"]) into sStyledTextA[theParaIndex]["metadata"]
end if
break
end switch
delete line -1 of sXMLTreeStateA["open node"]
end revEndXMLNode
command revStartXMLData pData
## this message can be sent when no node is "open".
switch line -1 of sXMLTreeStateA["open node"]
case "ul"
case "ol"
break
default
## Catch instances where string passed to ConvertXHTMLToStyledText doesn't start with <p> or <ol/ul>.
if sStyledTextIndexPathA is not an array then
put empty into sStyledTextA[1]
put StringToIndexPath("1.runs.1") into sStyledTextIndexPathA
end if
## If properties are changing on the text then start a new run.
if sXMLTreeStateA["run"] is not sXMLTreeStateA["previous run"] then
put the number of elements of sStyledTextA into theParaIndex
put StringToIndexPath(theParaIndex & ".runs." & the number of elements of sStyledTextA[theParaIndex]["runs"] + 1) into sStyledTextIndexPathA
_AddStylesAndColorToRun sStyledTextIndexPathA
end if
# Check among all lines as a pre may contain a span.
if "pre" is among the lines of sXMLTreeStateA["open node"] then
-- switch line -1 of sXMLTreeStateA["open node"]
-- case "pre"
## convert lines to vertical tabs
replace crlf with numToChar(11) in pData
replace cr with numToChar(11) in pData
replace lf with numToChar(11) in pData
-- break
-- end switch
end if
## Use after so data isn't lost in situations where white space outside
## of tags causes unwanted message to fire.
put uniencode(pData, "utf8") after sStyledTextA[sStyledTextIndexPathA]["unicodetext"]
-- put pData into sStyledTextA[sStyledTextIndexPathA]["text"] ## for testing
## Store run so we can compare next time through
put sXMLTreeStateA["run"] into sXMLTreeStateA["previous run"]
end switch
end revStartXMLData
on revXMLEndTree
put empty into sXMLTreeStateA
put empty into sStyledTextIndexPathA
end revXMLEndTree
/**
* \brief Escapes the predefined XML entities in a string.
*
* \param pStr The string to escape the characters in.
* \param pEscapeApostrophe Pass in true to escape apostrophes.
*
* \return String
*/
private function _EscapePredefinedXMLEntities pStr, pEscapeApostrophe
replace "&" with "&amp;" in pStr
replace "<" with "&lt;" in pStr
replace ">" with "&gt;" in pStr
replace quote with "&quot;" in pStr
if pEscapeApostrophe then
replace "'" with "&apos;" in pStr
end if
return pStr
end _EscapePredefinedXMLEntities
/**
* \brief Cleanses a string of non-printing characters that would mess up XML.
*
* \param pStr The string to work on.
*
* \return String
*/
private function _CleanseNonPrintingCharacters pStr
repeat for each item theNum in "0,1,2,3,4,5,6,7,8"
replace numToChar(theNum) with empty in pStr
end repeat
return pStr
end _CleanseNonPrintingCharacters
/**
* \brief Adds the currently active textStyle and textColor values to a run.
*
* \param pRunIndexPathA The index path array pointing to the run in the sStyledTextA array.
*
* \return empty
*/
command _AddStylesAndColorToRun pRunIndexPathA
if sXMLTreeStateA["run"]["textShift"] is not empty then \
put sXMLTreeStateA["run"]["textShift"] into sStyledTextA[pRunIndexPathA]["style"]["textShift"]
if sXMLTreeStateA["run"]["textStyle"] is not empty then \
put sXMLTreeStateA["run"]["textStyle"] into sStyledTextA[pRunIndexPathA]["style"]["textStyle"]
if sXMLTreeStateA["run"]["textColor"] is not empty then \
put sXMLTreeStateA["run"]["textColor"] into sStyledTextA[pRunIndexPathA]["style"]["textColor"]
if sXMLTreeStateA["run"]["linkText"] is not empty then \
put sXMLTreeStateA["run"]["linkText"] into sStyledTextA[pRunIndexPathA]["style"]["linkText"]
if sXMLTreeStateA["run"]["metadata"] is an array then \
put EncodeMetaDataArray(sXMLTreeStateA["run"]["metadata"]) into sStyledTextA[pRunIndexPathA]["metadata"]
return empty
end _AddStylesAndColorToRun
/**
* \brief Strips non numeric chars from a string (except commas). Used for converting CSS rgb(x,x,x) to an RGB color that LiveCode likes.
*
* \param pString The string to strip characters from.
*
* \return String
*/
private function _StripNonNumericListChars pString
local i
repeat with i = the number of chars of pString down to 1
put char i of pString into theChar
if theChar is not an integer AND theChar is not "," then
delete char i of pString
end if
end repeat
return pString
end _StripNonNumericListChars
/**
* \brief Adds an item to a list if it does not already exist.
*
* \param pItem The item to add.
* \param pList The list to add the item to.
*
* \return List
*/
private function _AddToList pItem, pList
set the wholematches to true
if pItem is not among the items of pList then
put pItem into item (the number of items of pList + 1) of pList
end if
return pList
end _AddToList
/**
* \brief Removes an item from a list.
*
* \param pItem The item to remove.
* \param pList The list to remove the item from.
*
* \return List
*/
private function _RemoveFromList pItem, pList
set the wholematches to true
put itemOffset(pItem, pList) into theItemNo
if theItemNo > 0 then delete item theItemNo of pList
return pList
end _RemoveFromList
/**
* |brief Encodes an array so it can be stored as the metadata property of a field chunk.
*
*/
function EncodeMetaDataArray pArrayA
if pArrayA is an array then
return base64Encode(arrayEncode(pArrayA))
else
return pArrayA
end if
end EncodeMetaDataArray
function DecodeMetaDataArray pData
try
return arrayDecode(base64Decode(pData))
catch e
return pData
end try
end DecodeMetaDataArray
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment