FmpRichTextJson_Encode | FmpRichText;OutputFormat;Include | All accounts | /* ===================================================================
Function: FmpRichTextJson_Encode( FmpRichText ; OutputFormat ; Include )
Purpose: Translates rich text content into plain-text encoded data which can later be translated back into the original rich text content.
Params:
- FmpRichText: FileMaker rich text, i.e. text content that may incorporate font, size, or formatting information.
- OutputFormat: Supply one of the following two values: "JSON", "FMP_CALC"
- Include: Leave empty to encode all rich text properties that this CF can handle. Otherwise, supply a string listing one or more of the following property names: "SIZE", "FONT", "STYLES", "COLOR"
Returns: Either JSON, or FileMaker calculation code, depending on the argument supplied for the OutputFormat parameter.
Support: Tested with FMPA v.16/17 on MacOS. May run elsewhere, too, though not tested.
Requires: Requires CF "EvaluateJavascript", which, in turn, requires MBS plugin.
---------------------------------------------------------------------
Comments:
- To restore original rich text from JSON output of this function, utilize companion CF "FmpRichTextJson_Decode".
- To restore original rich text from FMP calculation output of this function, utilize companion, run the FMP calculation through the native FileMaker command: Evaluate().
- In cases where the rich text content is of large size, it will be necessary to run several iterations of Evaluate, and concatenate the individual results together.
- In such a case, the output from this function will not be a single FMP calculation, but rather, a CR-delimited list of FMP calculations, where each list item is to be Evaluated individually.
---------------------------------------------------------------------
Credit:
- A portion of the following JavaScript library was used to implement HTML-decoding functionality: http://www.strictly-software.com/htmlencode (GPL, The MIT License)
---------------------------------------------------------------------
Version: 20180901_1104
Created: July 2018: Initial version.
Updates:
- Updated 01 Sept 2018: Updated Javascript: Extended special character handling list to include Unicode 8222 and 8223 (variants of quote chars), which (like other quote chars) will break Evaluate(), and thus need special care when serializing to FMP calculation.
Thanks to @hhenle for discovering/reporting this issue.
Author: https://community.filemaker.com/people/steve_ssh
HH comments:
- replaced call of CF "EvaluateJavaScript_ViaAvailablePlugin" with "EvaluateJavaScript", i.e. this CF requires MBS plugin
- support of all FM text styles added, this was updated by the author after an exchange with the in the FM community
=================================================================== */
Case(
OutputFormat <> "JS_LIBRARY" ;
Let([
/*------- CONSTANTS --------*/
~MAX_CHARS_PER_FMP_CALCULATION_TEXT = 20 * 1000; // I think this limit is actually larger than 20K -- maybe more like 30K ?
~javascript_lib = FmpRichTextJson_Encode( "" ; "JS_LIBRARY" ; "" );
~bs = "\\";
~sq = "'"; // Single quote char
/*------- INPUT --------*/
~input_as_css = GetAsCSS( FmpRichText );
~inclusions = Include;
~mode = Case( OutputFormat = "JSON"; "text2json" ; OutputFormat = "FMP_CALC" ; "text2fmpcalc" );
/*------- PRE-PROCESSING (quotation for use as JS strings ) --------*/
~input_css_quoted = ~sq & Substitute( ~input_as_css ; [ ~bs; ~bs & ~bs ]; [ Char( 13 ) ; "\r" ]; [ Char( 10 ) ; "\n" ]; [ Char( 9 ) ; "\t" ]; [ Char( 8232 ) ; "\u2028" ]; [ Char( 8233 ) ; "\u2029" ]; [ ~sq ; ~bs & ~sq ] ) & ~sq;
~inclusions_quoted = ~sq & Substitute( ~inclusions ; [ ~bs; ~bs & ~bs ]; [ Char( 13 ) ; "\r" ]; [ Char( 10 ) ; "\n" ]; [ Char( 9 ) ; "\t" ]; [ Char( 8232 ) ; "\u2028" ]; [ Char( 8233 ) ; "\u2029" ]; [ ~sq ; ~bs & ~sq ] ) & ~sq;
~mode_string =~sq & ~mode & ~sq;
/*------- JAVASCRIPT --------*/
/* Ref: function translate( input, mode, inclusions, maxCharsPerFmpCalculation ) */
~javascript_operation = "translate( " & ~input_css_quoted & ", " & ~mode_string & ", " & ~inclusions_quoted & ", " & ~MAX_CHARS_PER_FMP_CALCULATION_TEXT & " );";
~javascript_to_execute = List( ~javascript_lib ; ~javascript_operation )
];
/*------- RESULT --------*/
Case(
IsEmpty( ~mode ) ; "ERROR: Invalid OutputFormat parameter supplied. Valid arguments: \"FMP_CALC\", \"JSON\"." ;
EvaluateJavascript ( ~javascript_to_execute ) /* Modified CF that only work with MBS plugin */
)
);
/*------- JAVASCRIPT LIBRARIES --------*/
Let([
~RICH_TEXT_CONVERSION =
"¶/* Main point of entry ------------------------------------------------------------------------------------*/
¶/*
¶
¶ input and mode params:
¶
¶ • input = Result of GetAsCSS( someFmpRichText ) --> use mode of text2json to output JSON representation of rich text.
¶ • input = Result of GetAsCSS( someFmpRichText ) --> use mode of text2fmpcalc to output an FMP calculation expression that evaluates back to original rich text.
¶ • input = Rich text JSON from previous call to translate() --> use mode of json2fmpcalc to output an FMP calculation expression that evaluates back to original rich text.
¶
¶ inclusions:
¶
¶ • Supply a string containing any of the following to specify which properties to handle/include. Leave empty to include all properties:
¶
¶ font, size, color, styles
¶
¶ maxCharsPerFmpCalculation: Indicate the maximum number of allowed characters that can comprise a FMP calculation.
¶
¶ If FMP calculation output exceeds maximum size, it will be chunked into a CR-delimited list.
¶ Each list entry can be evaluated separately and then all individual results can be concatenated together.
¶
¶---------------------------------------------------------------------------------------------------------*/
¶
¶
¶function translate( input, mode, inclusions, maxCharsPerFmpCalculation ) {
¶
¶ if( (/^text2json$/i).test( mode ) ) {
¶
¶ return getFmpRichTextAsJson( input, inclusions );
¶ }
¶ else if( (/^text2fmpcalc$/i).test( mode ) ) {
¶
¶ return getAsFmpCalculation( input, null, inclusions, maxCharsPerFmpCalculation );
¶ }
¶ else if( (/^json2fmpcalc$/i).test( mode ) ) {
¶
¶ return getAsFmpCalculation( null, input, inclusions, maxCharsPerFmpCalculation );
¶ }
¶ else {
¶
¶ return 'ERROR: Unrecognized/invalid mode parameter: [' + mode + ']';
¶ }
¶}
¶
¶
¶
¶/* Translates the result of GetAsCSS( inputValue ) to JSON describing inputValue as rich text. */
¶
¶function getFmpRichTextAsJson( fmpCssString, inclusions ) {
¶
¶ var segmentArray = getFmpRichTextAsSegmentArray( fmpCssString, inclusions );
¶
¶ var result = JSON.stringify( segmentArray, null, ' ' );
¶
¶ /* Additional substitutions to prevent some systems from breaking when reading JSON: Line Separator, Paragraph Separator, Left Curly Quotes, Right Curly Quotes */
¶
¶ return result.replace( /\u2028/g, '\\\u2028' ).replace( /\u2029/g, '\\\u2029' ).replace( /\u201c/g, '\\\u201c' ).replace( /\u201d/g, '\\\u201d' );
¶
¶}
¶
¶
¶/* Translates the input to a FileMaker calculation which can be evaluated to restore inputValue as rich text. */
¶/* Supply only one of: fmpCssString or richTextJson */
¶
¶function getAsFmpCalculation( fmpCssString, richTextJson, inclusions, maxCharsPerFmpCalculation ) {
¶
¶ try {
¶
¶ var segmentArray = ( fmpCssString ) ? getFmpRichTextAsSegmentArray( fmpCssString ) : parseJsonToSegmentArray( richTextJson );
¶
¶ var calculationArray = segmentArray.map( translateSegmentToFmpCalculationChunk, getInclusions( inclusions ) );
¶
¶ return joinCalculationArray( calculationArray, maxCharsPerFmpCalculation );
¶
¶ }
¶ catch( err ) {
¶
¶ return 'ERROR: ' + err;
¶ }
¶}
¶
¶/* Basic validation and parsing of a string of JSON into an array of objects representing text segments. */
¶
¶function parseJsonToSegmentArray( richTextJson ) {
¶
¶ if( typeof richTextJson != 'string' || !(/^\s*\[/).test( richTextJson ) || !(/\]\s*$/).test( richTextJson ) ) {
¶
¶ throw 'Input does not appear to be a JSON array.';
¶ }
¶
¶ try{
¶
¶ return JSON.parse( richTextJson );
¶ }
¶ catch( parseErr ) {
¶
¶ throw 'JSON parse error: ' + parseErr;
¶ }
¶}
¶
¶
¶/* Joins FMP calculation segments into a single long FMP calculation string. */
¶/* Inserts returns to delimit final calculation into blocks which are small enough for FMP calculation engine to evaluate. */
¶
¶function joinCalculationArray( calculationArray, maxCharsPerFmpCalculation ) {
¶
¶ maxCharsPerFmpCalculation = maxCharsPerFmpCalculation || 20000;
¶
¶ var calculationString = '';
¶
¶ var currentBlockLength = 0;
¶
¶ var concatentationString = ' & ';
¶
¶ calculationArray.forEach( function( nextCalculationChunk ) {
¶
¶ var appendString = ( calculationString.length ) ? concatentationString: '';
¶
¶ appendString += nextCalculationChunk;
¶
¶ if( currentBlockLength + appendString.length > maxCharsPerFmpCalculation ) {
¶
¶ /* When starting a new block, we don't include concatenation string. */
¶ /* It will only get in the way when processing each block separately. */
¶
¶ calculationString += '\r' + nextCalculationChunk;
¶
¶ currentBlockLength = nextCalculationChunk.length;
¶ }
¶ else {
¶
¶ calculationString += appendString;
¶
¶ currentBlockLength += appendString.length;
¶ }
¶ });
¶
¶ return calculationString;
¶}
¶
¶
¶/* Returns an array of POJOs, each of which describes a \"segment\" of the CSS string. */
¶/* A segment is a block of text contained by a single html <span> element. */
¶
¶function getFmpRichTextAsSegmentArray( fmpCssString, inclusions ) {
¶
¶ var inputArray = ( fmpCssString || '' ).split( '</span>' );
¶
¶ inputArray.pop(); /* Splitting on </span> will generate an unwanted final array entry of an empty string; we remove it. */
¶
¶ return inputArray.map( convertSegmentStringtoPOJO, getInclusions( inclusions ) );
¶}
¶
¶/* Translates the supplied inclusion string into an object format. */
¶
¶function getInclusions( inclusions ) {
¶
¶ inclusions = inclusions || 'color font size styles';
¶
¶ return {
¶
¶ color: (/color/i).test( inclusions ),
¶
¶ font: (/font/i).test( inclusions ),
¶
¶ fontSize: (/size/i).test( inclusions ),
¶
¶ styles: (/styles/i).test( inclusions )
¶ };
¶
¶}
¶
¶/* Translates a text segment encapsulated by a <span> element into an object representation. */
¶
¶function convertSegmentStringtoPOJO( segmentString ) {
¶
¶ var segmentData = segmentString.replace( /\<br\/\>/g, '\r' ).split( '>' );
¶
¶ var formatString = segmentData[ 0 ];
¶
¶ var dataEscaped = segmentData[ 1 ];
¶
¶ var result = { data: undoHtmlMarkup( dataEscaped ) };
¶
¶ /* The 'this' object has been set to the 'inclusions' object, which tells us which properties to include. */
¶
¶ if( this.color ) {
¶
¶ result.color = parseColor( formatString );
¶ }
¶ if( this.font ) {
¶
¶ result.font = parseFont( formatString );
¶ }
¶ if( this.fontSize ) {
¶
¶ result.fontSize = parseFontSize( formatString );
¶ }
¶ if( this.styles ) {
¶
¶ result.styles = parseStyles( formatString );
¶ }
¶
¶ return result;
¶}
¶
¶function parseColor( formatString ) {
¶
¶ var color = (/[^-]color\: \#([^\;]+)\;/).exec( formatString ) || [ '', '' ];
¶
¶ var colorHex = color[1];
¶
¶ return colorHex ? { hex: colorHex, rgb: rgbFromHex( colorHex ) }: null;
¶}
¶
¶function parseFont( formatString ) {
¶
¶ var fontMatch = (/font-family\: \'([^\']+)\'\;/).exec( formatString ) || [ '', '' ];
¶
¶ return fontMatch[1];
¶}
¶
¶function parseFontSize( formatString ) {
¶
¶ var fontSizeMatch = (/font-size\: ([0-9]+)px/).exec( formatString ) || [ '', '' ];
¶
¶ return fontSizeMatch[1];
¶}
¶
¶function parseStyles( formatString ) {
¶
¶ var styleMatchers = getFmpStyleMatchers();
¶
¶ styles = {};
¶
¶ for( var style in styleMatchers ) {
¶
¶ styles[ style ] = styleMatchers[ style ].test( formatString ) ? true: false;
¶ }
¶
¶ return styles;
¶}
¶
¶function undoHtmlMarkup( markedUpData ) { /* Uses third-party code to perform html decoding. */
¶
¶ return Encoder.htmlDecode( markedUpData );
¶}
¶
¶function rgbFromHex( colorHex6Digits ) {
¶
¶ var rgb = {};
¶
¶ rgb.R = parseInt( colorHex6Digits.substring( 0, 2 ), 16 );
¶
¶ rgb.G = parseInt( colorHex6Digits.substring( 2, 4 ), 16 );
¶
¶ rgb.B = parseInt( colorHex6Digits.substring( 4, 6 ), 16 );
¶
¶ return rgb;
¶}
¶
¶/* Translates an object representation of a chunk of text into a FileMaker calculation, which can be evaluated to restore original rich text. */
¶
¶function translateSegmentToFmpCalculationChunk( segmentObject ) {
¶
¶ if( typeof segmentObject != 'object' ) {
¶
¶ throw 'Unexpected data-type [' + typeof segmentObject + '] encountered while attempting to read segment.';
¶ }
¶
¶ var outputCalc = prepTextForFmpCalculation( segmentObject.data );
¶
¶ /* The 'this' object has been set to the 'inclusions' object, which tells us which properties to include. */
¶
¶ if( this.font ) {
¶
¶ outputCalc = segmentObject.font ? addFontToFmpCalc( outputCalc, segmentObject.font ): outputCalc;
¶ }
¶ if( this.color ) {
¶
¶ outputCalc = segmentObject.color ? addColorToFmpCalc( outputCalc, segmentObject.color ) : outputCalc;
¶ }
¶ if( this.fontSize ) {
¶
¶ var fontSize = segmentObject.fontSize;
¶
¶ var fontSizeHasBeenHalvedForStyle = segmentObject.styles && ( segmentObject.styles.Superscript || segmentObject.styles.Subscript ); /* Superscript and Subscript result in the font-size being written to CSS as half of the original FMP rich text size */
¶
¶ /* We restore the original fontsize for FMP use. Note that, due to rounding in GetAsCSS, this restored value could be off by 1 pt (too large) if the original rich text font size was an odd-numbered value. */
¶
¶ fontSize = fontSizeHasBeenHalvedForStyle ? ( 2 * fontSize ): fontSize;
¶
¶ outputCalc = segmentObject.fontSize ? addSizeToFmpCalc( outputCalc, fontSize ) : outputCalc;
¶ }
¶ if( this.styles ) {
¶
¶ outputCalc = segmentObject.styles ? addStylesToFmpCalc( outputCalc, segmentObject.styles ) : outputCalc;
¶ }
¶
¶ return outputCalc;
¶}
¶
¶function prepTextForFmpCalculation( text ) {
¶
¶ var result = fmpQuote( text || '' );
¶
¶ result = translatePilcrows( result );
¶
¶ result = translateTabsAndNewlinesAndOtherCharsThatWouldBreakFmpCalculations( result );
¶
¶ return result;
¶}
¶
¶function translatePilcrows( text ) {
¶
¶ /* Pilcrow char (¶) is CodePoint 182. */
¶ /* Could probably hardcode the char directly, i.e. /\\¶/g, but choosing not to do so, just out of conservative paranoia. */
¶
¶ var pilcrowRegex = new RegExp( '\\\' + String.fromCharCode( 182 ), 'g' );
¶
¶ return text.replace( pilcrowRegex, '\" & Char(182) & \"' );
¶}
¶
¶function translateTabsAndNewlinesAndOtherCharsThatWouldBreakFmpCalculations( text ) {
¶
¶ var result = text;
¶
¶ var codePointsToReplace = [ 13, 10, 9, 8232, 2833, 8220, 8221, 8222, 8223 ];
¶
¶ codePointsToReplace.forEach( function( codepoint ) {
¶
¶ var regexp = new RegExp( String.fromCharCode( codepoint ), 'g' );
¶
¶ var replacementString = '\" & Char( ' + codepoint + ' ) & \"' ;
¶
¶ result = result.replace( regexp, replacementString );
¶ });
¶
¶ return result;
¶}
¶
¶function fmpQuote( text ) {
¶
¶ return '\"' + backslashAndDoubleQuoteEscape( text ) + '\"';
¶}
¶
¶function backslashAndDoubleQuoteEscape( text ) {
¶
¶ return text.replace( /\\\/g, '\\\\\\\' ).replace( /\\\"/g, '\\\\\"' );
¶}
¶
¶function addColorToFmpCalc( calculationChunk, color ) {
¶
¶ return 'TextColor(' + calculationChunk + '; RGB(' + color.rgb.R + ';' + color.rgb.G + ';' + color.rgb.B + '))';
¶}
¶
¶function addFontToFmpCalc( calculationChunk, font ) {
¶
¶ return 'TextFont(' + calculationChunk + '; ' + fmpQuote( font ) + ')';
¶}
¶
¶function addSizeToFmpCalc( calculationChunk, fontSize ) {
¶
¶ return 'TextSize(' + calculationChunk + '; ' + fontSize + ')';
¶}
¶
¶function addStylesToFmpCalc( calculationChunk, styles ) {
¶
¶ var result = calculationChunk;
¶
¶ var styleMatchers = getFmpStyleMatchers();
¶
¶ for( var style in styleMatchers ) {
¶
¶ if( styles[ style ] ) {
¶
¶ result = 'TextStyleAdd(' + result + '; ' + style + ')';
¶ }
¶ }
¶
¶ return result;
¶}
¶
¶function getFmpStyleMatchers() {
¶
¶ return {
¶
¶ Bold: /font-weight\: bold\;/,
¶
¶ Italic: /font-style\:italic\;/,
¶
¶ Underline: /text-decoration\:underline/,
¶
¶ StrikeThrough: /text-decoration\:line-through/,
¶
¶ HighlightYellow: /background-color\: \#FFFF00/,
¶
¶ Condense: /letter-spacing\: -2px/,
¶
¶ Extend: /letter-spacing\: 2px/,
¶
¶ SmallCaps: /font-variant\:small-caps/,
¶
¶ Uppercase: /text-transform\: uppercase/,
¶
¶ Lowercase: /text-transform\: lowercase/,
¶
¶ Titlecase: /text-transform\: capitalize/,
¶
¶ Superscript: /vertical-align\: text-top/,
¶
¶ Subscript: /vertical-align\: text-bottom/
¶
¶ };
¶}";
~HTML_DECODING_LIBRARY =
/* The following taken from: https://gist.github.com/ajinabraham/1af8216dfb6f959503e0#file-encoder-js */
"¶
¶/**
¶ * A Javascript object to encode and/or decode html characters using HTML or Numeric entities that handles double or partial encoding
¶ * Author: R Reid
¶ * source: http://www.strictly-software.com/htmlencode
¶ * Licences: GPL, The MIT License (MIT)
¶ * Copyright: (c) 2011 Robert Reid - Strictly-Software.com
¶ *
¶ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"¶), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
¶ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
¶ * THE SOFTWARE IS PROVIDED \"AS IS\"
¶, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
¶ *
¶ * Revision:
¶ * 2011-07-14, Jacques-Yves Bleau:
¶ * - fixed conversion error with capitalized accentuated characters
¶ * + converted arr1 and arr2 to object property to remove redundancy
¶ *
¶ * Revision:
¶ * 2011-11-10, Ce-Yi Hio:
¶ * - fixed conversion error with a number of capitalized entity characters
¶ *
¶ * Revision:
¶ * 2011-11-10, Rob Reid:
¶ * - changed array format
¶ *
¶ * Revision:
¶ * 2012-09-23, Alex Oss:
¶ * - replaced string concatonation in numEncode with string builder, push and join for peformance with ammendments by Rob Reid
¶ */
¶
¶Encoder = {
¶
¶ isEmpty : function(val){
¶ if(val){
¶ return ((val===null) || val.length==0 || /^\s+$/.test(val));
¶ }else{
¶ return true;
¶ }
¶ },
¶
¶ /* arrays for conversion from HTML Entities to Numerical values */
¶ arr1: [' ','¡','¢','£','¤','¥','¦','§','¨','©','ª','«','¬','­','®','¯','°','±','²','³','´','µ','¶','·','¸','¹','º','»','¼','½','¾','¿','À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë','Ì','Í','Î','Ï','Ð','Ñ','Ò','Ó','Ô','Õ','Ö','×','Ø','Ù','Ú','Û','Ü','Ý','Þ','ß','à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð','ñ','ò','ó','ô','õ','ö','÷','ø','ù','ú','û','ü','ý','þ','ÿ','"','&','<','>','Œ','œ','Š','š','Ÿ','ˆ','˜',' ',' ',' ','‌','‍','‎','‏','–','—','‘','’','‚','“','”','„','†','‡','‰','‹','›','€','ƒ','Α','Β','Γ','Δ','Ε','Ζ','Η','Θ','Ι','Κ','Λ','Μ','Ν','Ξ','Ο','Π','Ρ','Σ','Τ','Υ','Φ','Χ','Ψ','Ω','α','β','γ','δ','ε','ζ','η','θ','ι','κ','λ','μ','ν','ξ','ο','π','ρ','ς','σ','τ','υ','φ','χ','ψ','ω','ϑ','ϒ','ϖ','•','…','′','″','‾','⁄','℘','ℑ','ℜ','™','ℵ','←','↑','→','↓','↔','↵','⇐','⇑','⇒','⇓','⇔','∀','∂','∃','∅','∇','∈','∉','∋','∏','∑','−','∗','√','∝','∞','∠','∧','∨','∩','∪','∫','∴','∼','≅','≈','≠','≡','≤','≥','⊂','⊃','⊄','⊆','⊇','⊕','⊗','⊥','⋅','⌈','⌉','⌊','⌋','⟨','⟩','◊','♠','♣','♥','♦'],
¶ arr2: [' ','¡','¢','£','¤','¥','¦','§','¨','©','ª','«','¬','­','®','¯','°','±','²','³','´','µ','¶','·','¸','¹','º','»','¼','½','¾','¿','À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë','Ì','Í','Î','Ï','Ð','Ñ','Ò','Ó','Ô','Õ','Ö','×','Ø','Ù','Ú','Û','Ü','Ý','Þ','ß','à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð','ñ','ò','ó','ô','õ','ö','÷','ø','ù','ú','û','ü','ý','þ','ÿ','"','&','<','>','Œ','œ','Š','š','Ÿ','ˆ','˜',' ',' ',' ','‌','‍','‎','‏','–','—','‘','’','‚','“','”','„','†','‡','‰','‹','›','€','ƒ','Α','Β','Γ','Δ','Ε','Ζ','Η','Θ','Ι','Κ','Λ','Μ','Ν','Ξ','Ο','Π','Ρ','Σ','Τ','Υ','Φ','Χ','Ψ','Ω','α','β','γ','δ','ε','ζ','η','θ','ι','κ','λ','μ','ν','ξ','ο','π','ρ','ς','σ','τ','υ','φ','χ','ψ','ω','ϑ','ϒ','ϖ','•','…','′','″','‾','⁄','℘','ℑ','ℜ','™','ℵ','←','↑','→','↓','↔','↵','⇐','⇑','⇒','⇓','⇔','∀','∂','∃','∅','∇','∈','∉','∋','∏','∑','−','∗','√','∝','∞','∠','∧','∨','∩','∪','∫','∴','∼','≅','≈','≠','≡','≤','≥','⊂','⊃','⊄','⊆','⊇','⊕','⊗','⊥','⋅','⌈','⌉','⌊','⌋','〈','〉','◊','♠','♣','♥','♦'],
¶
¶ /* Convert HTML entities into numerical entities */
¶ HTML2Numerical : function(s){
¶ return this.swapArrayVals(s,this.arr1,this.arr2);
¶ },
¶
¶
¶ /* HTML Decode numerical and HTML entities back to original values */
¶ htmlDecode : function(s){
¶
¶ var c,m,d = s;
¶
¶ /* if(this.isEmpty(d)) return \"\"; modified this line to accommodate input which contains only significant whitespace, e.g. return chars. -ssh 2080710 */
¶ if(this.isEmpty(d)) return d;
¶
¶ /* convert HTML entites back to numerical entites first */
¶ d = this.HTML2Numerical(d);
¶
¶ /* look for numerical entities " */
¶ arr=d.match(/&#[0-9]{1,5};/g);
¶
¶ /* if no matches found in string then skip */
¶ if(arr!=null){
¶ for(var x=0;x<arr.length;x++){
¶ m = arr[x];
¶ c = m.substring(2,m.length-1); /* get numeric part which is refernce to unicode character */
¶ /* if its a valid number we can decode */
¶ if(c >= -32768 && c <= 65535){
¶ /* decode every single match within string */
¶ d = d.replace(m, String.fromCharCode(c));
¶ }else{
¶ d = d.replace(m, \"\"); /* invalid so replace with nada */
¶ }
¶ }
¶ }
¶
¶ return d;
¶ },
¶
¶
¶ /* Function to loop through an array swaping each item with the value from another array e.g swap HTML entities with Numericals */
¶ swapArrayVals : function(s,arr1,arr2){
¶ if(this.isEmpty(s)) return \"\";
¶ var re;
¶ if(arr1 && arr2){
¶ /* array lengths must match */
¶ if(arr1.length == arr2.length){
¶ for(var x=0,i=arr1.length;x<i;x++){
¶ re = new RegExp(arr1[x], 'g');
¶ s = s.replace(re,arr2[x]); /* swap arr1 item with matching item from arr2 */
¶ }
¶ }
¶ }
¶ return s;
¶ }
¶
¶};"
];
List( ~HTML_DECODING_LIBRARY ; ~RICH_TEXT_CONVERSION )
)
) |
|
|