Хорошо, я думаю, что у меня есть это сейчас.Это заняло немного больше времени, и выглядит немного менее аккуратно, чем я надеялся, но я написал статический служебный класс, чтобы заботиться о «переводе» из Flash-шрифтов в HTML.Это работает так:
- Оберните весь текст в
<![CDATA[]]>
теги.Как оказалось, это единственный способ безопасно сохранить пробелы при использовании преобразования XML - мне потребовалось почти три часа, чтобы понять, что XML.normalize()
просто отбрасывает пробелы, независимо от ignoreWhitespace=false
. - Нормализовать всеинформация о шрифте в
<style>
узлах.Это заменяет все теги <b>
, <u>
и т. Д., Но сохраняет иерархию DOM.Вся информация о стиле преобразуется в атрибуты с такими же именами, которые Flash использует для внутреннего разбора CSS. - Замените все узлы
<style>
на <span style="...">
, содержащие объединенные атрибуты стиля.В вашем примере были теги <font>
, но они не поддерживаются в HTML5. - Разверните элементы
<![CDATA[]]>
.
Результат все еще не сплющен, а вложен <span>
элементы разрешены, и это делает свою работу: я вставил вывод в простую HTML-страницу, и он выглядит почти так же, как во Flash.
Примечание. Я не проверял все разрешенные элементы HTML во Flash (<img>
и т. Д.), Поэтому не могу гарантировать, что он будет работать для всех - но он должен работать нормальнона все элементы в вашем примере.
Вот мой класс, с нетерпением жду ваших комментариев и критики:
Использование: var html:String = XMLTextUtil.flashTextToHtml (textField.htmlText);
package
{
public class XMLTextUtil
{
private static var mapping : Array = [ {html:"align", xml:"stageAlign"},
{html:"face", xml:"fontFamily"},
{html:"size", xml:"fontSize"},
{html:"blockindent", xml:"marginLeft"},
{html:"indent", xml:"textIndent"},
{html:"leftmargin", xml:"marginLeft"},
{html:"rightmargin", xml:"marginRight"},
{html:"letterspacing", xml:"letterSpacing"} ];
private static var typeMapping : Array = [ {attribute:"letterSpacing", type:"px"},
{attribute:"fontFamily", type:""},
{attribute:"fontSize", type:"px"},
{attribute:"fontStyle", type:""},
{attribute:"fontWeight", type:""},
{attribute:"textAlign", type:""},
{attribute:"textIndent", type:"px"},
{attribute:"textDecoration", type:""},
{attribute:"marginLeft", type:"px"},
{attribute:"marginRight", type:"px"} ];
private static function applyStyles ( html : XML ) : XML
{
var root : XML = applyTag( html );
for each ( var child:XML in html.children( ))
{
var kind : String = child.nodeKind( );
if ( kind == "element")
{
var next : XML = applyStyles( child );
if (next.name( ) != "span" || next.children( ).length( ) > 0)
{
root.appendChild( next );
}
}
else if (kind == "text") root.appendChild( child.copy( ) );
}
return root;
}
private static function applyTag ( html : XML ) : XML
{
var root : XML;
switch ( html.name( ).toString( ) )
{
case "style":
root = createElement( "span" );
root.@style = styleElementToString( html );
break;
case "p":
root = createElement( "p" );
break;
default:
root = cloneElement( html );
break;
}
return root;
}
private static function cloneElement ( html : XML ) : XML
{
var node : XML = createElement( html.name( ) );
for each (var attr:XML in html.attributes( ))
{
node["@" + attr.name( )] = html["@" + attr.name( )];
}
return node;
}
private static function createElement ( str : String) : XML
{
return new XML( "<" + str + " />" );
}
public static function flashTextToHtml ( str : String ) : String
{
XML.prettyPrinting = false;
XML.ignoreWhitespace = true;
var wrap : String = wrapTextInCdata( "<text>" + str + "</text>" );
var html : XML = new XML( wrap );
html = normalizeStyleTags( html );
var newHtml : XML = transformToHtml5( html );
return unwrapTextFromCdata( newHtml );
}
private static function getCssName (str : String ) : String
{
return str.replace( /[A-Z]/g, "-$&").toLowerCase( );
}
private static function getStyleName ( str : String ) : String
{
for each ( var map:Object in mapping)
{
if (str == map.html ) return map.xml;
}
return str;
}
private static function getCssType (str : String) : String
{
for each (var map:Object in typeMapping)
{
if (str == map.attribute) return map.type;
}
return "";
}
private static function normalizeStyleTags ( xmlElement : XML ) : XML
{
var xml : XML;
var child : XML;
var style : XML = new XML( "<style />" );
var name:String = xmlElement.name( ).toString( ).toLowerCase( );
switch ( name )
{
case "font":
case "textformat":
xml = style;
break;
case "b":
xml = style;
xml.@fontWeight = "bold";
break;
case "i":
xml = style;
xml.@fontStyle = "italic";
break;
case "u":
xml = style;
xml.@textDecoration = "underline";
break;
case "p":
xml = new XML( "<p />" );
xml.appendChild( style );
xml = style;
default:
xml = new XML( "<" + name + " />" );
break;
}
for each ( child in xmlElement.attributes( ))
{
var attname : String = getStyleName( child.name( ).toString( ).toLowerCase( ) );
xml["@" + attname] = xmlElement["@" + child.name( )];
switch (xml["@" + attname].toString( ))
{
case "LEFT":
case "RIGHT":
case "CENTER":
xml["@" + attname] = xml["@" + attname].toLowerCase( );
}
}
for each ( child in xmlElement.children( ))
{
var kind : String = child.nodeKind( );
if ( kind == "element") xml.appendChild( normalizeStyleTags( child ) );
else if (kind == "text")
xml.appendChild( new XML( "<![CDATA[" + child.valueOf( ) + "]]>" ) );
}
return xml;
}
private static function styleElementToString ( styleElement : XML ) : String
{
var style : Object = {};
var name : String = "";
var string : String = "";
for each ( var attribute:XML in styleElement.attributes( ))
{
name = attribute.name( ).toString( );
style[name] = styleElement.attribute( name ).valueOf( );
}
for ( name in style)
{
if ( style[name] != null)
string += getCssName( name ) + ":" + style[name] + getCssType( name ) + ";";
}
return string;
}
private static function transformToHtml5 ( xmlText : XML ) : XML
{
var root : XML = new XML( "<text />" );
for each ( var p:XML in xmlText.p)
{
root.appendChild( applyStyles( p ) );
}
return root;
}
public static function unwrapTextFromCdata (xmlText : XML) : String
{
return xmlText.toXMLString( ).replace( /(\<\!\[CDATA\[)|(\]\]\>)/g, "" );
}
public static function wrapTextInCdata (htmlText : String) : String
{
return htmlText.replace( /(?:\>)([\s|\w]+)(?:\<)/g, "><![CDATA[$1]]><" );
}
}
}