Пример #1
0
        public static XElement LoadStream(XmlReader reader, XName rootName, params XName[] streamNames)
        {
            ArgumentNullException.ThrowIfNull(reader);
            ArgumentNullException.ThrowIfNull(rootName);
            ArgumentNullException.ThrowIfNull(streamNames);

            for (int i = 0; i < streamNames.Length; i++)
            {
                if (streamNames[i] == null)
                {
                    throw new ArgumentNullException("streamNames[" + i + "]");
                }
            }
            if (reader.MoveToContent() != XmlNodeType.Element)
            {
                throw new InvalidOperationException(string.Format("The reader should be on a node of type '{0}'.", XmlNodeType.Element));
            }
            XElement     source     = new XElement(rootName);
            StreamLoader loader     = new StreamLoader(reader, streamNames);
            XName        streamName = streamNames.Length > 0 ? streamNames[0] : null;

            loader.ReadElementUntil(source, streamName);
            if (streamName != null)
            {
                source.AddAnnotation(loader);
            }
            return(source);
        }
Пример #2
0
        /// <summary>
        /// Adds UVML annotations to the specified UVML element tree.
        /// </summary>
        /// <param name="dataSourceTypeName">The name of the data source wrapper associated with this tree.</param>
        /// <param name="root">The root of the UVML element tree to annotate.</param>
        public static void AddUvmlAnnotations(String dataSourceTypeName, XElement root)
        {
            Contract.RequireNotEmpty(dataSourceTypeName, nameof(dataSourceTypeName));
            Contract.Require(root, nameof(root));

            var templates = 0;

            if (root.Annotation<UvmlMetadataAnnotation>() != null)
                return;

            root.AddAnnotation(new UvmlMetadataAnnotation());
            AddUvmlAnnotations(dataSourceTypeName, root, ref templates);
        }
Пример #3
0
 private static XObject CloneWithAnnotation(XNode node)
 {
     XElement element = node as XElement;
     if (element != null)
     {
         XElement newElement = new XElement(element.Name,
             element.Attributes(),
             element.Nodes().Select(n => CloneWithAnnotation(n)));
         if (element.Annotation<MatchSemaphore>() != null)
             newElement.AddAnnotation(element.Annotation<MatchSemaphore>());
     }
     return node;
 }
 public static ASupportElement GetInstance(XElement definition)
 {
     Type eType = ElementType (definition);
     if (eType != null) {
         if (definition.Annotation (eType) != null)
             return definition.Annotation (eType) as ASupportElement;
         else {
             var instance = Activator.CreateInstance (eType, new object[] { definition });
             definition.AddAnnotation (instance);
             return instance as ASupportElement;
         }
     } else
         return null;
 }
		public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) {
			var record = (ConstructorParameterTypeRecord)((BamlRecordNode)node).Record;

			var elem = new XElement(ctx.GetXamlNsName("TypeExtension", parent.Xaml));
			elem.AddAnnotation(ctx.ResolveType(0xfd4d)); // Known type - TypeExtension

			var bamlElem = new BamlElement(node);
			bamlElem.Xaml = elem;
			parent.Xaml.Element.Add(elem);

			var type = ctx.ResolveType(record.TypeId);
			var typeName = ctx.ToString(parent.Xaml, type);
			elem.Add(new XElement(ctx.GetPseudoName("Ctor"), typeName));

			return bamlElem;
		}
		public BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent) {
			var record = (DefAttributeKeyTypeRecord)((BamlRecordNode)node).Record;
			var type = ctx.ResolveType(record.TypeId);
			var typeName = ctx.ToString(parent.Xaml, type);
			var key = (XamlResourceKey)node.Annotation;

			var bamlElem = new BamlElement(node);
			bamlElem.Xaml = new XElement(ctx.GetXamlNsName("Key", parent.Xaml));
			parent.Xaml.Element.Add(bamlElem.Xaml.Element);

			var typeElem = new XElement(ctx.GetXamlNsName("TypeExtension", parent.Xaml));
			typeElem.AddAnnotation(ctx.ResolveType(0xfd4d)); // Known type - TypeExtension
			typeElem.Add(new XElement(ctx.GetPseudoName("Ctor"), typeName));
			bamlElem.Xaml.Element.Add(typeElem);

			key.KeyElement = bamlElem;

			return bamlElem;
		}
            public void AddEventXElementShouldBeNotifiedWithAnnotations()
            {
                var el = new XElement("test");
                bool changedNotification = false;
                var handler = new EventHandler<XObjectChangeEventArgs>(
                    (sender, cea) =>
                    {
                        changedNotification = true;
                    }
                );

                el.AddAnnotation(new object());
                el.Changed += handler;
                var child = new XElement("test2");
                el.Add(child);
                Assert.True(changedNotification);
                changedNotification = false;
                child.Add(new XAttribute("a", "b"));
                Assert.True(changedNotification);
            }
		public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) {
			var record = (PropertyTypeReferenceRecord)((BamlRecordNode)node).Record;
			var attr = ctx.ResolveProperty(record.AttributeId);
			var type = ctx.ResolveType(record.TypeId);
			var typeName = ctx.ToString(parent.Xaml, type);

			var elem = new BamlElement(node);

			var elemAttr = ctx.ResolveProperty(record.AttributeId);
			elem.Xaml = new XElement(elemAttr.ToXName(ctx, null));

			elem.Xaml.Element.AddAnnotation(elemAttr);
			parent.Xaml.Element.Add(elem.Xaml.Element);

			var typeElem = new XElement(ctx.GetXamlNsName("TypeExtension", parent.Xaml));
			typeElem.AddAnnotation(ctx.ResolveType(0xfd4d)); // Known type - TypeExtension
			typeElem.Add(new XElement(ctx.GetPseudoName("Ctor"), typeName));
			elem.Xaml.Element.Add(typeElem);

			elemAttr.DeclaringType.ResolveNamespace(elem.Xaml, ctx);
			elem.Xaml.Element.Name = elemAttr.ToXName(ctx, null);

			return elem;
		}
 private static object ProcessHyperlinkToBookmark(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement element)
 {
     var style = new Dictionary<string, string>();
     var a = new XElement(Xhtml.a,
         new XAttribute("href", "#" + (string) element.Attribute(W.anchor)),
         element.Elements(W.r).Select(run => ConvertRun(wordDoc, settings, run)));
     style.Add("text-decoration", "none");
     a.AddAnnotation(style);
     return a;
 }
        private static object CreateBorderDivs(WordprocessingDocument wordDoc, HtmlConverterSettings settings, IEnumerable<XElement> elements)
        {
            return elements.GroupAdjacent(e =>
                {
                    var pBdr = e.Elements(W.pPr).Elements(W.pBdr).FirstOrDefault();
                    if (pBdr != null)
                    {
                        var indStr = string.Empty;
                        var ind = e.Elements(W.pPr).Elements(W.ind).FirstOrDefault();
                        if (ind != null)
                            indStr = ind.ToString(SaveOptions.DisableFormatting);
                        return pBdr.ToString(SaveOptions.DisableFormatting) + indStr;
                    }
                    return e.Name == W.tbl ? "table" : string.Empty;
                })
                .Select(g =>
                {
                    if (g.Key == string.Empty)
                    {
                        return (object) GroupAndVerticallySpaceNumberedParagraphs(wordDoc, settings, g, 0m);
                    }
                    if (g.Key == "table")
                    {
                        return g.Select(gc => ConvertToHtmlTransform(wordDoc, settings, gc, false, 0));
                    }
                    var pPr = g.First().Elements(W.pPr).First();
                    var pBdr = pPr.Element(W.pBdr);
                    var style = new Dictionary<string, string>();
                    GenerateBorderStyle(pBdr, W.top, style, BorderType.Paragraph);
                    GenerateBorderStyle(pBdr, W.right, style, BorderType.Paragraph);
                    GenerateBorderStyle(pBdr, W.bottom, style, BorderType.Paragraph);
                    GenerateBorderStyle(pBdr, W.left, style, BorderType.Paragraph);

                    var currentMarginLeft = 0m;
                    var ind = pPr.Element(W.ind);
                    if (ind != null)
                    {
                        var leftInInches = (decimal?) ind.Attribute(W.left)/1440m ?? 0;
                        var hangingInInches = -(decimal?) ind.Attribute(W.hanging)/1440m ?? 0;
                        currentMarginLeft = leftInInches + hangingInInches;

                        style.AddIfMissing("margin-left",
                            currentMarginLeft > 0m
                                ? string.Format(NumberFormatInfo.InvariantInfo, "{0:0.00}in", currentMarginLeft)
                                : "0");
                    }

                    var div = new XElement(Xhtml.div,
                        GroupAndVerticallySpaceNumberedParagraphs(wordDoc, settings, g, currentMarginLeft));
                    div.AddAnnotation(style);
                    return div;
                })
            .ToList();
        }
        /*
         * Handle:
         * - b
         * - bdr
         * - caps
         * - color
         * - dstrike
         * - highlight
         * - i
         * - position
         * - rFonts
         * - shd
         * - smallCaps
         * - spacing
         * - strike
         * - sz
         * - u
         * - vanish
         * - vertAlign
         *
         * Don't handle:
         * - em
         * - emboss
         * - fitText
         * - imprint
         * - kern
         * - outline
         * - shadow
         * - w
         *
         */

        private static object ConvertRun(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement run)
        {
            var rPr = run.Element(W.rPr);
            if (rPr == null)
                return run.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, 0m));

            // hide all content that contains the w:rPr/w:webHidden element
            if (rPr.Element(W.webHidden) != null)
                return null;

            var style = DefineRunStyle(run);
            object content = run.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, 0m));

            // Wrap content in h:sup or h:sub elements as necessary.
            if (rPr.Element(W.vertAlign) != null)
            {
                XElement newContent = null;
                var vertAlignVal = (string)rPr.Elements(W.vertAlign).Attributes(W.val).FirstOrDefault();
                switch (vertAlignVal)
                {
                    case "superscript":
                        newContent = new XElement(Xhtml.sup, content);
                        break;
                    case "subscript":
                        newContent = new XElement(Xhtml.sub, content);
                        break;
                }
                if (newContent != null && newContent.Nodes().Any())
                    content = newContent;
            }

            var langAttribute = GetLangAttribute(run);

            XEntity runStartMark;
            XEntity runEndMark;
            DetermineRunMarks(run, rPr, style, out runStartMark, out runEndMark);

            if (style.Any() || langAttribute != null || runStartMark != null)
            {
                style.AddIfMissing("margin", "0");
                style.AddIfMissing("padding", "0");
                var xe = new XElement(Xhtml.span,
                    langAttribute,
                    runStartMark,
                    content,
                    runEndMark);

                xe.AddAnnotation(style);
                content = xe;
            }
            return content;
        }
        private static List<object> TransformElementsPrecedingTab(WordprocessingDocument wordDoc, HtmlConverterSettings settings,
            List<XElement> elementsPrecedingTab, XElement firstTabRun)
        {
            var tabWidth = firstTabRun != null
                ? (decimal?) firstTabRun.Elements(W.tab).Attributes(PtOpenXml.TabWidth).FirstOrDefault() ?? 0m
                : 0m;
            var precedingElementsWidth = elementsPrecedingTab
                .Elements()
                .Where(c => c.Attributes(PtOpenXml.TabWidth).Any())
                .Select(e => (decimal) e.Attribute(PtOpenXml.TabWidth))
                .Sum();
            var totalWidth = precedingElementsWidth + tabWidth;

            var txElementsPrecedingTab = elementsPrecedingTab
                .Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, 0m))
                .ToList();
            if (txElementsPrecedingTab.Count > 1)
            {
                var span = new XElement(Xhtml.span, txElementsPrecedingTab);
                var spanStyle = new Dictionary<string, string>
                {
                    { "display", "inline-block" },
                    { "text-indent", "0" },
                    { "width", string.Format(NumberFormatInfo.InvariantInfo, "{0:0.000}in", totalWidth) }
                };
                span.AddAnnotation(spanStyle);
            }
            else if (txElementsPrecedingTab.Count == 1)
            {
                var element = txElementsPrecedingTab.First() as XElement;
                if (element != null)
                {
                    var spanStyle = element.Annotation<Dictionary<string, string>>();
                    spanStyle.AddIfMissing("display", "inline-block");
                    spanStyle.AddIfMissing("text-indent", "0");
                    spanStyle.AddIfMissing("width", string.Format(NumberFormatInfo.InvariantInfo, "{0:0.000}in", totalWidth));
                }
            }
            return txElementsPrecedingTab;
        }
Пример #13
0
 // typeScope is applied for child items, rather than obj itself.
 private XElement SerializeXElement(object obj, Type defaultType, XName name, SerializationScope typeScope)
 {
     Debug.Assert(obj != null && defaultType != null && name != null);
     var objType = obj.GetType();
     var objTypeName = _Builder.GlobalScope.GetName(objType);
     if (objTypeName == null)
         throw new NotSupportedException(string.Format(Prompts.UnregisteredType, objType, _Builder.GlobalScope));
     var s = _Builder.GetSerializer(objType);
     var e = new XElement(name);
     //如果名义类型和实际类型不同,则注明实际类型。
     //如果是 TypeScope 中未定义的类型,则使用对应的元素名,而不使用 xsi:type
     if (name != objTypeName && objType != defaultType)
     {
         //先将 XName 加入批注,到根节点中处理。
         e.AddAnnotation(objTypeName);
     }
     //一般不会调用到此处,除非 obj 是根部节点,或是集合中的一项。
     if (s == null)
         throw new NotSupportedException(string.Format(Prompts.UnregisteredType, objType, typeScope));
     EnterObjectSerialization(obj);
     s.Serialize(e, obj, this, typeScope);
     ExitObjectSerialization(obj);
     return e;
 }
 private static object ProcessTableRow(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement element,
     decimal currentMarginLeft)
 {
     var style = new Dictionary<string, string>();
     int? trHeight = (int?) element.Elements(W.trPr).Elements(W.trHeight).Attributes(W.val).FirstOrDefault();
     if (trHeight != null)
         style.AddIfMissing("height",
             string.Format(NumberFormatInfo.InvariantInfo, "{0:0.00}in", (decimal) trHeight/1440m));
     var htmlRow = new XElement(Xhtml.tr,
         element.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft)));
     if (style.Any())
         htmlRow.AddAnnotation(style);
     return htmlRow;
 }
 private static object ProcessTable(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement element, decimal currentMarginLeft)
 {
     var style = new Dictionary<string, string>();
     style.AddIfMissing("border-collapse", "collapse");
     style.AddIfMissing("border", "none");
     var bidiVisual = element.Elements(W.tblPr).Elements(W.bidiVisual).FirstOrDefault();
     var tblW = element.Elements(W.tblPr).Elements(W.tblW).FirstOrDefault();
     if (tblW != null)
     {
         var type = (string)tblW.Attribute(W.type);
         if (type != null && type == "pct")
         {
             var w = (int)tblW.Attribute(W._w);
             style.AddIfMissing("width", (w / 50) + "%");
         }
     }
     var tblInd = element.Elements(W.tblPr).Elements(W.tblInd).FirstOrDefault();
     if (tblInd != null)
     {
         var tblIndType = (string)tblInd.Attribute(W.type);
         if (tblIndType != null)
         {
             if (tblIndType == "dxa")
             {
                 var width = (decimal?)tblInd.Attribute(W._w);
                 if (width != null)
                 {
                     style.AddIfMissing("margin-left",
                         width > 0m
                             ? string.Format(NumberFormatInfo.InvariantInfo, "{0}pt", width / 20m)
                             : "0");
                 }
             }
         }
     }
     var tableDirection = bidiVisual != null ? new XAttribute("dir", "rtl") : new XAttribute("dir", "ltr");
     style.AddIfMissing("margin-bottom", ".001pt");
     var table = new XElement(Xhtml.table,
         // TODO: Revisit and make sure the omission is covered by appropriate CSS.
         // new XAttribute("border", "1"),
         // new XAttribute("cellspacing", 0),
         // new XAttribute("cellpadding", 0),
         tableDirection,
         element.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft)));
     table.AddAnnotation(style);
     var jc = (string)element.Elements(W.tblPr).Elements(W.jc).Attributes(W.val).FirstOrDefault() ?? "left";
     XAttribute dir = null;
     XAttribute jcToUse = null;
     if (bidiVisual != null)
     {
         dir = new XAttribute("dir", "rtl");
         if (jc == "left")
             jcToUse = new XAttribute("align", "right");
         else if (jc == "right")
             jcToUse = new XAttribute("align", "left");
         else if (jc == "center")
             jcToUse = new XAttribute("align", "center");
     }
     else
     {
         jcToUse = new XAttribute("align", jc);
     }
     var tableDiv = new XElement(Xhtml.div,
         dir,
         jcToUse,
         table);
     return tableDiv;
 }
Пример #16
0
        public Place ObjectToElement(INakedObjectAdapter nakedObjectAdapter) {
            Log.Debug("objectToElement(" + DoLog("object", nakedObjectAdapter) + ")");

            var nos = (IObjectSpec) nakedObjectAdapter.Spec;

            Log.Debug("objectToElement(NO): create element and nof:title");
            XElement element = Schema.CreateElement(XmlDocument, nos.ShortName, nos.FullName, nos.SingularName, nos.PluralName);
            NofMetaModel.AppendNofTitle(element, nakedObjectAdapter.TitleString());

            Log.Debug("objectToElement(NO): create XS element for NOF class");
            XElement xsElement = Schema.CreateXsElementForNofClass(XsdDocument, element, topLevelElementWritten);

            // hack: every element in the XSD schema apart from first needs minimum cardinality setting.
            topLevelElementWritten = true;

            var place = new Place(nakedObjectAdapter, element);

            NofMetaModel.SetAttributesForClass(element, OidOrHashCode(nakedObjectAdapter));

            IAssociationSpec[] fields = nos.Properties;
            Log.Debug("objectToElement(NO): processing fields");

            var seenFields = new List<string>();

            foreach (IAssociationSpec field in fields) {
                string fieldName = field.Id;

                Log.Debug("objectToElement(NO): " + DoLog("field", fieldName));

                // Skip field if we have seen the name already
                // This is a workaround for getLastActivity(). This method exists
                // in AbstractNakedObject, but is not (at some level) being picked up
                // by the dot-net reflector as a property. On the other hand it does
                // exist as a field in the meta model (NakedObjectSpecification).
                //
                // Now, to re-expose the lastactivity field for .Net, a deriveLastActivity()
                // has been added to BusinessObject. This caused another field ofthe
                // same name, ultimately breaking the XSD.

                if (seenFields.Contains(fieldName)) {
                    Log.Debug("objectToElement(NO): " + DoLog("field", fieldName) + " SKIPPED");
                    continue;
                }
                seenFields.Add(fieldName);

                XNamespace ns = Schema.GetUri();

                var xmlFieldElement = new XElement(ns + fieldName);

                XElement xsdFieldElement;
                var oneToOneAssociation = field as IOneToOneAssociationSpec;
                var oneToManyAssociation = field as IOneToManyAssociationSpec;

                if (field.ReturnSpec.IsParseable && oneToOneAssociation != null) {
                    Log.Debug("objectToElement(NO): " + DoLog("field", fieldName) + " is value");

                    IObjectSpec fieldNos = field.ReturnSpec;
                    // skip fields of type XmlValue
                    if (fieldNos != null &&
                        fieldNos.FullName != null &&
                        fieldNos.FullName.EndsWith("XmlValue")) {
                        continue;
                    }

                    XElement xmlValueElement = xmlFieldElement; // more meaningful locally scoped name

                    try {
                        INakedObjectAdapter value = oneToOneAssociation.GetNakedObject(nakedObjectAdapter);

                        // a null value would be a programming error, but we protect
                        // against it anyway
                        if (value == null) {
                            continue;
                        }

                        ITypeSpec valueNos = value.Spec;

                        // XML
                        NofMetaModel.SetAttributesForValue(xmlValueElement, valueNos.ShortName);

                        bool notEmpty = (value.TitleString().Length > 0);
                        if (notEmpty) {
                            string valueStr = value.TitleString();
                            xmlValueElement.Add(new XText(valueStr));
                        }
                        else {
                            NofMetaModel.SetIsEmptyAttribute(xmlValueElement, true);
                        }
                    }
                    catch (Exception) {
                        Log.Warn("objectToElement(NO): " + DoLog("field", fieldName) + ": getField() threw exception - skipping XML generation");
                    }

                    // XSD
                    xsdFieldElement = Schema.CreateXsElementForNofValue(xsElement, xmlValueElement);
                }
                else if (oneToOneAssociation != null) {
                    Log.Debug("objectToElement(NO): " + DoLog("field", fieldName) + " is IOneToOneAssociation");

                    XElement xmlReferenceElement = xmlFieldElement; // more meaningful locally scoped name

                    try {
                        INakedObjectAdapter referencedNakedObjectAdapter = oneToOneAssociation.GetNakedObject(nakedObjectAdapter);
                        string fullyQualifiedClassName = field.ReturnSpec.FullName;

                        // XML
                        NofMetaModel.SetAttributesForReference(xmlReferenceElement, Schema.Prefix, fullyQualifiedClassName);

                        if (referencedNakedObjectAdapter != null) {
                            NofMetaModel.AppendNofTitle(xmlReferenceElement, referencedNakedObjectAdapter.TitleString());
                        }
                        else {
                            NofMetaModel.SetIsEmptyAttribute(xmlReferenceElement, true);
                        }
                    }
                    catch (Exception) {
                        Log.Warn("objectToElement(NO): " + DoLog("field", fieldName) + ": getAssociation() threw exception - skipping XML generation");
                    }

                    // XSD
                    xsdFieldElement = Schema.CreateXsElementForNofReference(xsElement, xmlReferenceElement, oneToOneAssociation.ReturnSpec.FullName);
                }
                else if (oneToManyAssociation != null) {
                    Log.Debug("objectToElement(NO): " + DoLog("field", fieldName) + " is IOneToManyAssociation");

                    XElement xmlCollectionElement = xmlFieldElement; // more meaningful locally scoped name

                    try {
                        INakedObjectAdapter collection = oneToManyAssociation.GetNakedObject(nakedObjectAdapter);
                        ITypeOfFacet facet = collection.GetTypeOfFacetFromSpec();

                        IObjectSpecImmutable referencedTypeNos = facet.GetValueSpec(collection, metamodelManager.Metamodel);
                        string fullyQualifiedClassName = referencedTypeNos.FullName;

                        // XML
                        NofMetaModel.SetNofCollection(xmlCollectionElement, Schema.Prefix, fullyQualifiedClassName, collection, nakedObjectManager);
                    }
                    catch (Exception) {
                        Log.Warn("objectToElement(NO): " + DoLog("field", fieldName) + ": get(obj) threw exception - skipping XML generation");
                    }

                    // XSD
                    xsdFieldElement = Schema.CreateXsElementForNofCollection(xsElement, xmlCollectionElement, oneToManyAssociation.ReturnSpec.FullName);
                }
                else {
                    Log.Info("objectToElement(NO): " + DoLog("field", fieldName) + " is unknown type; ignored");
                    continue;
                }

                if (xsdFieldElement != null) {
                    xmlFieldElement.AddAnnotation(xsdFieldElement);
                }

                // XML
                Log.Debug("objectToElement(NO): invoking mergeTree for field");
                MergeTree(element, xmlFieldElement);

                // XSD
                if (xsdFieldElement != null) {
                    Log.Debug("objectToElement(NO): adding XS element for field to schema");
                    Schema.AddFieldXsElement(xsElement, xsdFieldElement);
                }
            }

            return place;
        }
Пример #17
0
 /// Accept deleted paragraphs.
 ///
 /// Group together all paragraphs that contain w:p/w:pPr/w:rPr/w:del elements.  Make a
 /// second group for the content element immediately following a paragraph that contains
 /// a w:del element.  The code uses the approach of dealing with paragraph content at
 /// 'levels', ignoring paragraph content at other levels.  Form a new paragraph that
 /// contains the content of the grouped paragraphs with deleted paragraph marks, and the
 /// content of the paragraph immediately following a paragraph that contains a deleted
 /// paragraph mark.  Include in the new paragraph the paragraph properties from the
 /// paragraph following.  When assembling the new paragraph, use a transform that collapses
 /// the paragraph nodes when adding content, thereby preserving custom XML and content
 /// controls.
 private static void AnnotateBlockContentElements(XElement contentContainer)
 {
     // For convenience, there is a ParagraphInfo annotation on the contentContainer.
     // It contains the same information as the ParagraphInfo annotation on the first
     //   paragraph.
     if (contentContainer.Annotation<BlockContentInfo>() != null)
         return;
     XElement firstContentElement = contentContainer
         .Elements()
         .DescendantsAndSelf()
         .FirstOrDefault(e => e.Name == W.p || e.Name == W.tbl);
     // Add the annotation on the contentContainer.
     BlockContentInfo currentContentInfo = new BlockContentInfo()
     {
         PreviousBlockContentElement = null,
         ThisBlockContentElement = firstContentElement,
         NextBlockContentElement = null
     };
     // Add as annotation even though NextParagraph is not set yet.
     contentContainer.AddAnnotation(currentContentInfo);
     while (true)
     {
         currentContentInfo.ThisBlockContentElement.AddAnnotation(currentContentInfo);
         // Find next sibling content element.
         XElement nextContentElement = null;
         XElement current = currentContentInfo.ThisBlockContentElement;
         while (true)
         {
             nextContentElement = current
                 .ElementsAfterSelf()
                 .DescendantsAndSelf()
                 .FirstOrDefault(e => e.Name == W.p || e.Name == W.tbl);
             if (nextContentElement != null)
             {
                 currentContentInfo.NextBlockContentElement = nextContentElement;
                 break;
             }
             current = current.Parent;
             // When we've backed up the tree to the contentContainer, we're done.
             if (current == contentContainer)
                 return;
         }
         currentContentInfo = new BlockContentInfo()
         {
             PreviousBlockContentElement = currentContentInfo.ThisBlockContentElement,
             ThisBlockContentElement = nextContentElement,
             NextBlockContentElement = null
         };
     }
 }
Пример #18
0
        //  Creates an &lt;xs:element&gt; element defining the presence of the named element
        //  representing a class
        public XElement CreateXsElementForNofClass(XDocument xsdDoc, XElement element, bool addCardinality)
        {
            // gather details from XML element
            string localName = element.Name.LocalName;

            //	<xs:element name="AO11ConfirmAnimalRegistration">
            //		<xs:complexType>
            //			<xs:sequence>
            //             <xs:element ref="nof:title"/>
            //             <!-- placeholder -->
            //			</xs:sequence>
            //			<xs:attribute ref="nof:feature"
            //			              default="class"/>
            //			<xs:attribute ref="nof:oid"/>
            //			<xs:attribute ref="nof:annotation"/>
            //			<xs:attribute ref="nof:fqn"/>
            //	    </xs:complexType>
            //	</xs:element>

            // xs:element/@name="class name"
            // add to XML schema as a global attribute
            XElement xsElementForNofClassElement = XsMetaModel.CreateXsElementElement(xsdDoc, localName, addCardinality);

            // xs:element/xs:complexType
            // xs:element/xs:complexType/xs:sequence
            XElement xsComplexTypeElement = XsMetaModel.ComplexTypeFor(xsElementForNofClassElement);
            XElement xsSequenceElement = XsMetaModel.SequenceFor(xsComplexTypeElement);

            // xs:element/xs:complexType/xs:sequence/xs:element ref="nof:title"
            XElement xsTitleElement = XsMetaModel.CreateXsElement(Helper.DocFor(xsSequenceElement), "element");
            xsTitleElement.SetAttributeValue("ref", NofMetaModel.NofMetamodelNsPrefix + ":" + "title");
            xsSequenceElement.Add(xsTitleElement);
            XsMetaModel.SetXsCardinality(xsTitleElement, 0, 1);

            // xs:element/xs:complexType/xs:sequence/xs:element ref="extensions"
            //addXsElementForAppExtensions(xsSequenceElement, extensions);

            // xs:element/xs:complexType/xs:attribute ...
            XsMetaModel.AddXsNofFeatureAttributeElements(xsComplexTypeElement, "class");
            XsMetaModel.AddXsNofAttribute(xsComplexTypeElement, "oid");
            XsMetaModel.AddXsNofAttribute(xsComplexTypeElement, "fqn");
            XsMetaModel.AddXsNofAttribute(xsComplexTypeElement, "singular");
            XsMetaModel.AddXsNofAttribute(xsComplexTypeElement, "plural");
            XsMetaModel.AddXsNofAttribute(xsComplexTypeElement, "annotation");

            element.AddAnnotation(xsElementForNofClassElement);

            return xsElementForNofClassElement;
        }
            private Location GetIncludeElementLocation(XElement includeElement, ref string currentXmlFilePath, ref CSharpSyntaxNode originatingSyntax)
            {
                Location location = includeElement.Annotation<Location>();
                if (location != null)
                {
                    return location;
                }

                // If we are not in an XML file, then we must be in a source file.  Since we're traversing the XML tree in the same
                // order as the DocumentationCommentWalker, we can access the elements of includeElementNodes in order.
                if (currentXmlFilePath == null)
                {
                    Debug.Assert(nextSourceIncludeElementIndex < sourceIncludeElementNodes.Length);
                    Debug.Assert(originatingSyntax == null);
                    originatingSyntax = sourceIncludeElementNodes[nextSourceIncludeElementIndex];
                    location = originatingSyntax.Location;
                    nextSourceIncludeElementIndex++;

                    // #line shall not affect the base path:
                    currentXmlFilePath = location.GetLineSpan().Path;
                }
                else
                {
                    location = XmlLocation.Create(includeElement, currentXmlFilePath);
                }

                Debug.Assert(location != null);
                includeElement.AddAnnotation(location);
                return location;
            }
Пример #20
0
        static void ApplyAnnotationToElement(XElement element, XElement annotation, object obj)
        {
            Contract.Requires<ArgumentNullException>(element != null);
            Contract.Requires<ArgumentNullException>(annotation != null);
            Contract.Requires<ArgumentNullException>(obj != null);

            element.AddAnnotation(obj);
        }
        private static object ProcessBookmarkStart(XElement element)
        {
            var name = (string) element.Attribute(W.name);
            if (name == null) return null;

            var style = new Dictionary<string, string>();
            var a = new XElement(Xhtml.a,
                new XAttribute("id", name),
                new XText(""));
            style.Add("text-decoration", "none");
            a.AddAnnotation(style);
            return a;
        }
        private static object ProcessBreak(XElement element)
        {
            XElement span = null;
            var tabWidth = (decimal?) element.Attribute(PtOpenXml.TabWidth);
            if (tabWidth != null)
            {
                span = new XElement(Xhtml.span);
                span.AddAnnotation(new Dictionary<string, string>
                {
                    { "margin", string.Format(NumberFormatInfo.InvariantInfo, "0 0 0 {0:0.00}in", tabWidth) },
                    { "padding", "0 0 0 0" }
                });
            }

            var paragraph = element.Ancestors(W.p).FirstOrDefault();
            var isBidi = paragraph != null &&
                         paragraph.Elements(W.pPr).Elements(W.bidi).Any(b => b.Attribute(W.val) == null ||
                                                                             b.Attribute(W.val).ToBoolean() == true);
            var zeroWidthChar = isBidi ? new XEntity("#x200f") : new XEntity("#x200e");

            return new object[]
            {
                new XElement(Xhtml.br),
                zeroWidthChar,
                span,
            };
        }
        /*
         * Handle:
         * - b
         * - bdr
         * - caps
         * - color
         * - dstrike
         * - highlight
         * - i
         * - position
         * - rFonts
         * - shd
         * - smallCaps
         * - spacing
         * - strike
         * - sz
         * - u
         * - vanish
         * - vertAlign
         *
         * Don't handle:
         * - em
         * - emboss
         * - fitText
         * - imprint
         * - kern
         * - outline
         * - shadow
         * - w
         * 
         */

        private static object ConvertRun(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement run)
        {
            var style = new Dictionary<string, string>();
            var sn = (string)run.Attribute(PtOpenXml.StyleName);
            if (sn != null)
                style.Add("PtStyleName", sn);

            var rPr = run.Element(W.rPr);

            if (rPr == null)
            {
                object content2 = run.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, 0m));
                return content2;
            }

            // hide all content that contains the w:rPr/w:webHidden element
            if (rPr.Element(W.webHidden) != null)
                return null;

            // W.bdr
            if (rPr.Element(W.bdr) != null && (string)rPr.Elements(W.bdr).Attributes(W.val).FirstOrDefault() != "none")
            {
                style.AddIfMissing("border", "solid windowtext 1.0pt");
                style.AddIfMissing("padding", "0in");
            }

            // W.color
            string color = (string)rPr.Elements(W.color).Attributes(W.val).FirstOrDefault();
            if (color != null)
                CreateColorProperty("color", color, style);

            // W.highlight
            string highlight = (string)rPr.Elements(W.highlight).Attributes(W.val).FirstOrDefault();
            if (highlight != null)
                CreateColorProperty("background", highlight, style);

            // W.shd
            string shade = (string)rPr.Elements(W.shd).Attributes(W.fill).FirstOrDefault();
            if (shade != null)
                CreateColorProperty("background", shade, style);

            // Pt.FontName
            string font = null;
            if (run.Element(W.sym) != null)
                font = (string)run.Elements(W.sym).Attributes(W.font).FirstOrDefault();
            else
                font = (string)run.Attributes(PtOpenXml.FontName).FirstOrDefault();
            if (font != null)
                CreateFontCssProperty(font, style);

            // W.sz
            var languageType = (string)run.Attribute(PtOpenXml.LanguageType);
            decimal? sz = null;
            if (languageType == "bidi")
                sz = (decimal?)rPr.Elements(W.szCs).Attributes(W.val).FirstOrDefault();
            else
                sz = (decimal?)rPr.Elements(W.sz).Attributes(W.val).FirstOrDefault();
            if (sz != null)
                style.AddIfMissing("font-size", string.Format("{0}pt", sz / 2.0m));

            // W.caps
            if (getBoolProp(rPr, W.caps))
                style.AddIfMissing("text-transform", "uppercase");

            // W.smallCaps
            if (getBoolProp(rPr, W.smallCaps))
                style.AddIfMissing("font-variant", "small-caps");

            // W.spacing
            decimal? spacingInTwips = (decimal?)rPr.Elements(W.spacing).Attributes(W.val).FirstOrDefault();
            if (spacingInTwips != null)
                style.AddIfMissing("letter-spacing", string.Format("{0}pt", spacingInTwips / 20));

            // W.position
            decimal? position = (decimal?)rPr.Elements(W.position).Attributes(W.val).FirstOrDefault();
            if (position != null)
            {
                style.AddIfMissing("position", "relative");
                style.AddIfMissing("top", string.Format("{0}pt", -(position / 2)));
            }

            // W.vanish
            if (getBoolProp(rPr, W.vanish))
                style.AddIfMissing("display", "none");

            object content = run.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, 0m));

            // W.u
            if (rPr.Element(W.u) != null && (string)rPr.Elements(W.u).Attributes(W.val).FirstOrDefault() != "none")
            {
                var newContent = new XElement(Xhtml.u, content);
                if (newContent.Nodes().Any())
                    content = newContent;
                style.AddIfMissing("text-decoration", "underline");
            }

            // W.i
            if (getBoolProp(rPr, W.i))
            {
                var newContent = new XElement(Xhtml.i, content);
                if (newContent.Nodes().Any())
                    content = newContent;
                style.AddIfMissing("font-style", "italic");
            }

            // W.b
            if (getBoolProp(rPr, W.b))
            {
                var newContent = new XElement(Xhtml.b, content);
                if (newContent.Nodes().Any())
                    content = newContent;
                style.AddIfMissing("font-weight", "bold");
            }
            else
            {
                style.AddIfMissing("font-weight", "normal");
            }

            // W.strike
            if (getBoolProp(rPr, W.strike) || getBoolProp(rPr, W.dstrike))
            {
                var newContent = new XElement(Xhtml.s, content);
                if (newContent.Nodes().Any())
                    content = newContent;
                style.AddIfMissing("text-decoration", "line-through");
            }

            // W.vertAlign
            if (rPr.Element(W.vertAlign) != null && (string)rPr.Elements(W.vertAlign).Attributes(W.val).FirstOrDefault() == "superscript")
            {
                var newContent = new XElement(Xhtml.sup, content);
                if (newContent.Nodes().Any())
                    content = newContent;
            }

            if (rPr.Element(W.vertAlign) != null && (string)rPr.Elements(W.vertAlign).Attributes(W.val).FirstOrDefault() == "subscript")
            {
                var newContent = new XElement(Xhtml.sub, content);
                if (newContent.Nodes().Any())
                    content = newContent;
            }

            var rtl = rPr.Element(W.rtl);
            var isRtl = rtl != null;

            var paragraph = run.Ancestors(W.p).FirstOrDefault();
            var paraBidi = paragraph
                .Elements(W.pPr)
                .Elements(W.bidi)
                .Where(b => b.Attribute(W.val) == null || b.Attribute(W.val).ToBoolean() == true)
                .FirstOrDefault();
            var paraIsBidi = paraBidi != null;

            string lang = null;
            if (languageType == "western")
                lang = (string)rPr.Elements(W.lang).Attributes(W.val).FirstOrDefault();
            else if (languageType == "bidi")
                lang = (string)rPr.Elements(W.lang).Attributes(W.bidi).FirstOrDefault();
            else if (languageType == "eastAsia")
                lang = (string)rPr.Elements(W.lang).Attributes(W.eastAsia).FirstOrDefault();

            // only do the following for text runs.
            XEntity runStartMark = null;
            XEntity runEndMark = null;

            // Can't add directional marks if the font-family is symbol - they are visible, and display as a ?
            bool addDirectionalMarks = true;
            if (style.ContainsKey("font-family"))
            {
                if (style["font-family"].ToLower() == "symbol")
                    addDirectionalMarks = false;
            }
            if (addDirectionalMarks)
            {
                if (run.Element(W.t) != null)
                {
                    if (isRtl)
                    {
                        runStartMark = new XEntity("#x200f"); // RLM
                        runEndMark = new XEntity("#x200f"); // RLM
                    }
                    else
                    {
                        if (paraIsBidi)
                        {
                            runStartMark = new XEntity("#x200e"); // LRM
                            runEndMark = new XEntity("#x200e"); // LRM
                        }
                    }
                }
            }

            string defaultLanguage = "en-US"; // todo need to get defaultLanguage
            if (lang == null)
                lang = defaultLanguage;
            XAttribute langAttribute = new XAttribute("lang", lang);
            if (lang == defaultLanguage)
                langAttribute = null;

            if (style.Any() || isRtl || langAttribute != null)
            {
                style.AddIfMissing("margin", "0in");
                style.AddIfMissing("padding", "0in");
                var xe = new XElement(Xhtml.span,
                    langAttribute,
                    runStartMark,
                    content,
                    runEndMark);

                xe.AddAnnotation(style);
                content = xe;
            }
            return content;
        }
        private static object ProcessTableCell(WordprocessingDocument wordDoc, HtmlConverterSettings settings, XElement element)
        {
            var style = new Dictionary<string, string>();
            XAttribute colSpan = null;
            XAttribute rowSpan = null;

            var tcPr = element.Element(W.tcPr);
            if (tcPr != null)
            {
                if ((string) tcPr.Elements(W.vMerge).Attributes(W.val).FirstOrDefault() == "restart")
                {
                    var currentRow = element.Parent.ElementsBeforeSelf(W.tr).Count();
                    var currentCell = element.ElementsBeforeSelf(W.tc).Count();
                    var tbl = element.Parent.Parent;
                    int rowSpanCount = 1;
                    currentRow += 1;
                    while (true)
                    {
                        var row = tbl.Elements(W.tr).Skip(currentRow).FirstOrDefault();
                        if (row == null)
                            break;
                        var cell2 = row.Elements(W.tc).Skip(currentCell).FirstOrDefault();
                        if (cell2 == null)
                            break;
                        if (cell2.Elements(W.tcPr).Elements(W.vMerge).FirstOrDefault() == null)
                            break;
                        if ((string) cell2.Elements(W.tcPr).Elements(W.vMerge).Attributes(W.val).FirstOrDefault() == "restart")
                            break;
                        currentRow += 1;
                        rowSpanCount += 1;
                    }
                    rowSpan = new XAttribute("rowspan", rowSpanCount);
                }

                if (tcPr.Element(W.vMerge) != null &&
                    (string) tcPr.Elements(W.vMerge).Attributes(W.val).FirstOrDefault() != "restart")
                    return null;

                if (tcPr.Element(W.vAlign) != null)
                {
                    var vAlignVal = (string) tcPr.Elements(W.vAlign).Attributes(W.val).FirstOrDefault();
                    if (vAlignVal == "top")
                        style.AddIfMissing("vertical-align", "top");
                    else if (vAlignVal == "center")
                        style.AddIfMissing("vertical-align", "middle");
                    else if (vAlignVal == "bottom")
                        style.AddIfMissing("vertical-align", "bottom");
                    else
                        style.AddIfMissing("vertical-align", "middle");
                }
                style.AddIfMissing("vertical-align", "top");

                if ((string) tcPr.Elements(W.tcW).Attributes(W.type).FirstOrDefault() == "dxa")
                {
                    decimal width = (int) tcPr.Elements(W.tcW).Attributes(W._w).FirstOrDefault();
                    style.AddIfMissing("width", string.Format(NumberFormatInfo.InvariantInfo, "{0}pt", width/20m));
                }
                if ((string) tcPr.Elements(W.tcW).Attributes(W.type).FirstOrDefault() == "pct")
                {
                    decimal width = (int) tcPr.Elements(W.tcW).Attributes(W._w).FirstOrDefault();
                    style.AddIfMissing("width", string.Format(NumberFormatInfo.InvariantInfo, "{0:0.0}%", width/50m));
                }

                var tcBorders = tcPr.Element(W.tcBorders);
                GenerateBorderStyle(tcBorders, W.top, style, BorderType.Cell);
                GenerateBorderStyle(tcBorders, W.right, style, BorderType.Cell);
                GenerateBorderStyle(tcBorders, W.bottom, style, BorderType.Cell);
                GenerateBorderStyle(tcBorders, W.left, style, BorderType.Cell);

                CreateStyleFromShd(style, tcPr.Element(W.shd));

                var gridSpan = tcPr.Elements(W.gridSpan).Attributes(W.val).Select(a => (int?) a).FirstOrDefault();
                if (gridSpan != null)
                    colSpan = new XAttribute("colspan", (int) gridSpan);
            }
            style.AddIfMissing("padding-top", "0");
            style.AddIfMissing("padding-bottom", "0");

            var cell = new XElement(Xhtml.td,
                rowSpan,
                colSpan,
                CreateBorderDivs(wordDoc, settings, element.Elements()));
            cell.AddAnnotation(style);
            return cell;
        }
        private static object ConvertToHtmlTransform(WordprocessingDocument wordDoc,
            HtmlConverterSettings settings, XNode node,
            bool suppressTrailingWhiteSpace,
            decimal currentMarginLeft)
        {
            XElement element = node as XElement;
            if (element != null)
            {
                if (element.Name == W.document)
                    return new XElement(Xhtml.html,
                        new XElement(Xhtml.head,
                            new XElement(Xhtml.meta,
                                new XAttribute("http-equiv", "Content-Type"),
                                new XAttribute("content", "text/html; charset=utf-8")),
                            new XElement(Xhtml.meta,
                                new XAttribute("name", "Generator"),
                                new XAttribute("content", "PowerTools for Open XML")),
                            settings.PageTitle != null ? new XElement(Xhtml.title,
                                new XText(settings.PageTitle)) : null
                        ),
                        element.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft))
                    );

                // Transform the w:body element to the XHTML h:body element.
                if (element.Name == W.body)
                {
                    var sectionDivContent = new XElement(Xhtml.body,
                        CreateSectionDivs(wordDoc, settings, element));
                    return sectionDivContent;
                }

                if (element.Name == W.p)
                {
                    var bidi = element
                        .Elements(W.pPr)
                        .Elements(W.bidi)
                        .Where(b => b.Attribute(W.val) == null || b.Attribute(W.val).ToBoolean() == true)
                        .FirstOrDefault();
                    var isBidi = bidi != null;
                    string styleId = (string)element.Elements(W.pPr).Elements(W.pStyle)
                        .Attributes(W.val).FirstOrDefault();
                    if (styleId != null)
                    {
                        XElement style = wordDoc.MainDocumentPart.StyleDefinitionsPart
                            .GetXDocument().Root.Elements(W.style)
                            .Where(s => (string)s.Attribute(W.styleId) == styleId)
                            .FirstOrDefault();
                        if (style != null)
                        {
                            int? outlineLevel = (int?)style.Elements(W.pPr)
                                .Elements(W.outlineLvl).Attributes(W.val).FirstOrDefault();
                            if (outlineLevel != null && outlineLevel <= 5)
                            {
                                XName elementName = Xhtml.xhtml + string.Format("h{0}",
                                    outlineLevel + 1);
                                return ConvertParagraph(wordDoc, settings, element, elementName, suppressTrailingWhiteSpace, currentMarginLeft, isBidi);
                            }
                            else
                            {
                                XName elementName = Xhtml.p;
                                var o = ConvertParagraph(wordDoc, settings, element, elementName, suppressTrailingWhiteSpace, currentMarginLeft, isBidi);
                                return o;
                            }
                        }
                    }
                    else
                    {
                        XName elementName = Xhtml.p;
                        var o = ConvertParagraph(wordDoc, settings, element, elementName, suppressTrailingWhiteSpace, currentMarginLeft, isBidi);
                        return o;
                    }
                }

                // Transform hyperlinks to the XHTML h:A element.
                if (element.Name == W.hyperlink && element.Attribute(R.id) != null)
                {
                    try
                    {
                        return new XElement(Xhtml.A,
                            new XAttribute("href",
                                wordDoc.MainDocumentPart
                                    .HyperlinkRelationships
                                    .Where(x => x.Id == (string)element.Attribute(R.id))
                                    .First()
                                    .Uri
                            ),
                            element.Elements(W.r).Select(run => ConvertRun(wordDoc, settings, run))
                        );
                    }
                    catch (UriFormatException)
                    {
                        return element.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft));
                    }
                }

                // Transform hyperlinks to bookmarks to the XHTML h:A element.
                if (element.Name == W.hyperlink && element.Attribute(W.anchor) != null)
                {
                    var style = new Dictionary<string, string>();
                    var a = new XElement(Xhtml.A,
                        new XAttribute("href", "#" + (string)element.Attribute(W.anchor)),
                        element
                            .Elements(W.r)
                            .Select(run => ConvertRun(wordDoc, settings, run)));
                    style.Add("text-decoration", "none");
                    a.AddAnnotation(style);
                    return a;
                }

                // Transform contents of runs.
                if (element.Name == W.r)
                    return ConvertRun(wordDoc, settings, element);

                // Transform w:bookmarkStart into anchor
                if (element.Name == W.bookmarkStart)
                {
                    var name = (string)element.Attribute(W.name);
                    if (name != null)
                    {
                        var style = new Dictionary<string, string>();
                        var a = new XElement(Xhtml.A,
                            new XAttribute("id", name),
                            new XText(""));
                        style.Add("text-decoration", "none");
                        a.AddAnnotation(style);
                        return a;
                    }
                }

                // Transform every w:t element to a text node.
                if (element.Name == W.t)
                {
                    var textWithEntities = ConvertEntities(element.Value);
                    return textWithEntities;
                }

                // Transform symbols to spans
                if (element.Name == W.sym)
                {
                    var cs = (string)element.Attribute(W._char);
                    var c = Convert.ToInt32(cs, 16);
                    var symbolSpan = new XElement(Xhtml.span, new XEntity(string.Format("#{0}", ((int)c).ToString())));
                    return symbolSpan;
                }

                // Transform tabs that have the pt:TabWidth attribute set
                if (element.Name == W.tab)
                {
                    var tabWidthAtt = element.Attribute(PtOpenXml.TabWidth);
                    if (tabWidthAtt != null)
                    {
                        var leader = (string)element.Attribute(PtOpenXml.Leader);
                        var tabWidth = (decimal)tabWidthAtt;
                        var style = new Dictionary<string, string>();
                        XElement span;
                        if (leader != null)
                        {
                            var leaderChar = ".";
                            if (leader == "hyphen")
                                leaderChar = "-";
                            else if (leader == "dot")
                                leaderChar = ".";
                            else if (leader == "underscore")
                                leaderChar = "_";

                            var runContainingTabToReplace = element.Ancestors(W.r).First();
                            var fontNameAtt = runContainingTabToReplace.Attribute(PtOpenXml.pt + "FontName");
                            if (fontNameAtt == null)
                                fontNameAtt = runContainingTabToReplace.Ancestors(W.p).First()
                                    .Attribute(PtOpenXml.pt + "FontName");

                            var dummyRun = new XElement(W.r,
                                fontNameAtt,
                                runContainingTabToReplace.Elements(W.rPr),
                                new XElement(W.t, leaderChar));

                            var widthOfLeaderChar = CalcWidthOfRunInTwips(dummyRun);

                            bool forceArial = false;
                            if (widthOfLeaderChar == 0)
                            {
                                dummyRun = new XElement(W.r,
                                    new XAttribute(PtOpenXml.FontName, "Arial"),
                                    runContainingTabToReplace.Elements(W.rPr),
                                    new XElement(W.t, leaderChar));
                                widthOfLeaderChar = CalcWidthOfRunInTwips(dummyRun);
                                forceArial = true;
                            }

                            if (widthOfLeaderChar != 0)
                            {
                                var numberOfLeaderChars = (int)(Math.Floor((tabWidth * 1440) / widthOfLeaderChar));
                                if (numberOfLeaderChars < 0)
                                    numberOfLeaderChars = 0;
                                span = new XElement(Xhtml.span,
                                    " " + "".PadRight(numberOfLeaderChars, leaderChar[0]) + " ");
                                style.Add("margin", "0 0 0 0");
                                style.Add("padding", "0 0 0 0");
                                style.Add("width", string.Format("{0:0.00}in", tabWidth));
                                style.Add("text-align", "center");
                                if (forceArial)
                                    style.Add("font-family", "Arial");
                            }
                            else
                            {
                                span = new XElement(Xhtml.span, " ");
                                style.Add("margin", "0 0 0 0");
                                style.Add("padding", "0 0 0 0");
                                style.Add("width", string.Format("{0:0.00}in", tabWidth));
                                style.Add("text-align", "center");
                                if (leader == "underscore")
                                {
                                    style.Add("text-decoration", "underline");
                                }
                            }
                        }
                        else
                        {
#if false
                            var bidi = element
                                .Ancestors(W.p)
                                .Take(1)
                                .Elements(W.pPr)
                                .Elements(W.bidi)
                                .Where(b => b.Attribute(W.val) == null || b.Attribute(W.val).ToBoolean() == true)
                                .FirstOrDefault();
                            var isBidi = bidi != null;
                            if (isBidi)
                                span = new XElement(Xhtml.span, new XEntity("#x200f")); // RLM
                            else
                                span = new XElement(Xhtml.span, new XEntity("#x200e")); // LRM
#else
                            span = new XElement(Xhtml.span, new XEntity("nbsp"));
#endif
                            style.Add("margin", string.Format("0 0 0 {0:0.00}in", tabWidth));
                            style.Add("padding", "0 0 0 0");
                        }
                        span.AddAnnotation(style);
                        return span;
                    }
                }

                // Transform w:br to h:br.
                if (element.Name == W.br || element.Name == W.cr)
                {
                    XElement span = null;
                    var tabWidth = (decimal?)element.Attribute(PtOpenXml.TabWidth);
                    if (tabWidth != null)
                    {
                        span = new XElement(Xhtml.span);
                        var style = new Dictionary<string, string>();
                        style.Add("margin", string.Format("0 0 0 {0:0.00}in", tabWidth));
                        style.Add("padding", "0 0 0 0");
                        span.AddAnnotation(style);
                    }
                    var paragraph = element.Ancestors(W.p).FirstOrDefault();
                    bool isBidi = false;
                    if (paragraph != null)
                    {
                        var bidi = paragraph
                            .Elements(W.pPr)
                            .Elements(W.bidi)
                            .Where(b => b.Attribute(W.val) == null || b.Attribute(W.val).ToBoolean() == true)
                            .FirstOrDefault();
                        isBidi = bidi != null;
                    }
                    var br = new XElement(Xhtml.br);
                    XEntity zeroWidthChar = null;
                    if (isBidi)
                        zeroWidthChar = new XEntity("#x200f"); // RLM
                    else
                        zeroWidthChar = new XEntity("#x200e"); // LRM
                    return new object[] {
                        br,
                        zeroWidthChar,
                        span,
                    };
                }

                // Transform w:noBreakHyphen to '-'
                if (element.Name == W.noBreakHyphen)
                    return new XText("-");

                // Transform w:tbl to h:tbl.
                if (element.Name == W.tbl)
                {
                    var style = new Dictionary<string, string>();
                    style.AddIfMissing("border-collapse", "collapse");
                    style.AddIfMissing("border", "none");
                    var bidiVisual = element.Elements(W.tblPr).Elements(W.bidiVisual).FirstOrDefault();
                    var tblW = element.Elements(W.tblPr).Elements(W.tblW).FirstOrDefault();
                    if (tblW != null)
                    {
                        var type = (string)tblW.Attribute(W.type);
                        if (type != null && type == "pct")
                        {
                            var w = (int)tblW.Attribute(W._w);
                            style.AddIfMissing("width", (w / 50).ToString() + "%");
                        }
                    }
                    var tblInd = element.Elements(W.tblPr).Elements(W.tblInd).FirstOrDefault();
                    if (tblInd != null)
                    {
                        var tblIndType = (string)tblInd.Attribute(W.type);
                        if (tblIndType != null)
                        {
                            if (tblIndType == "dxa")
                            {
                                var width = (decimal?)tblInd.Attribute(W._w);
                                if (width != null)
                                {
                                    style.AddIfMissing("margin-left", string.Format("{0}pt", width / 20m));
                                }
                            }
                        }
                    }
                    XAttribute tableDirection = null;
                    if (bidiVisual != null)
                    {
                        tableDirection = new XAttribute("dir", "rtl");
                    }
                    else
                    {
                        tableDirection = new XAttribute("dir", "ltr");
                    }
                    style.AddIfMissing("margin-bottom", ".001pt");
                    var table = new XElement(Xhtml.table,
                        new XAttribute("border", "1"),
                        new XAttribute("cellspacing", 0),
                        new XAttribute("cellpadding", 0),
                        tableDirection,
                        element.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft)));
                    table.AddAnnotation(style);
                    var jc = (string)element.Elements(W.tblPr).Elements(W.jc).Attributes(W.val).FirstOrDefault();
                    if (jc == null)
                        jc = "left";
                    XAttribute dir = null;
                    XAttribute jcToUse = null;
                    if (bidiVisual != null)
                    {
                        dir = new XAttribute("dir", "rtl");
                        if (jc == "left")
                            jcToUse = new XAttribute("align", "right");
                        else if (jc == "right")
                            jcToUse = new XAttribute("align", "left");
                        else if (jc == "center")
                            jcToUse = new XAttribute("align", "center");
                    }
                    else
                    {
                        jcToUse = new XAttribute("align", jc);
                    }
                    var tableDiv = new XElement(Xhtml.div,
                        dir,
                        jcToUse,
                        table);
                    return tableDiv;
                }

                // Transform w:tr to h:tr.
                if (element.Name == W.tr)
                {
                    var style = new Dictionary<string, string>();
                    int? trHeight = (int?)element.Elements(W.trPr).Elements(W.trHeight).Attributes(W.val).FirstOrDefault();
                    if (trHeight != null)
                        style.AddIfMissing("height", string.Format("{0}in", (decimal)trHeight / 1440m));
                    var htmlRow = new XElement(Xhtml.tr,
                        element.Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft)));
                    if (style.Any())
                        htmlRow.AddAnnotation(style);
                    return htmlRow;
                }

                // Transform w:tc to h:td.
                if (element.Name == W.tc)
                {
                    var style = new Dictionary<string, string>();
                    XAttribute colSpan = null;
                    XAttribute rowSpan = null;

                    var tcPr = element.Element(W.tcPr);
                    if (tcPr != null)
                    {
                        if ((string)tcPr.Elements(W.vMerge).Attributes(W.val).FirstOrDefault() == "restart")
                        {
                            var currentRow = element.Parent.ElementsBeforeSelf(W.tr).Count();
                            var currentCell = element.ElementsBeforeSelf(W.tc).Count();
                            var tbl = element.Parent.Parent;
                            int rowSpanCount = 1;
                            currentRow += 1;
                            while (true)
                            {
                                var row = tbl.Elements(W.tr).Skip(currentRow).FirstOrDefault();
                                if (row == null)
                                    break;
                                var cell2 = row.Elements(W.tc).Skip(currentCell).FirstOrDefault();
                                if (cell2 == null)
                                    break;
                                if (cell2.Elements(W.tcPr).Elements(W.vMerge).FirstOrDefault() == null)
                                    break;
                                if ((string)cell2.Elements(W.tcPr).Elements(W.vMerge).Attributes(W.val).FirstOrDefault() == "restart")
                                    break;
                                currentRow += 1;
                                rowSpanCount += 1;
                            }
                            rowSpan = new XAttribute("rowspan", rowSpanCount);
                        }

                        if (tcPr.Element(W.vMerge) != null && (string)tcPr.Elements(W.vMerge).Attributes(W.val).FirstOrDefault() != "restart")
                            return null;

                        if (tcPr.Element(W.vAlign) != null)
                        {
                            var vAlignVal = (string)tcPr.Elements(W.vAlign).Attributes(W.val).FirstOrDefault();
                            if (vAlignVal == "top")
                                style.AddIfMissing("vertical-align", "top");
                            else if (vAlignVal == "center")
                                style.AddIfMissing("vertical-align", "middle");
                            else if (vAlignVal == "bottom")
                                style.AddIfMissing("vertical-align", "bottom");
                            else
                                style.AddIfMissing("vertical-align", "middle");
                        }
                        style.AddIfMissing("vertical-align", "top");

                        if ((string)tcPr.Elements(W.tcW).Attributes(W.type).FirstOrDefault() == "dxa")
                        {
                            decimal width = (int)tcPr.Elements(W.tcW).Attributes(W._w).FirstOrDefault();
                            style.AddIfMissing("width", string.Format("{0}pt", width / 20m));
                        }
                        if ((string)tcPr.Elements(W.tcW).Attributes(W.type).FirstOrDefault() == "pct")
                        {
                            decimal width = (int)tcPr.Elements(W.tcW).Attributes(W._w).FirstOrDefault();
                            style.AddIfMissing("width", string.Format("{0:0.0}%", width / 50m));
                        }

                        var tcBorders = tcPr.Element(W.tcBorders);
                        GenerateBorderStyle(tcBorders, W.top, style, BorderType.Cell);
                        GenerateBorderStyle(tcBorders, W.right, style, BorderType.Cell);
                        GenerateBorderStyle(tcBorders, W.bottom, style, BorderType.Cell);
                        GenerateBorderStyle(tcBorders, W.left, style, BorderType.Cell);

                        CreateStyleFromShd(style, tcPr.Element(W.shd));

                        var gridSpan = (int?)tcPr.Elements(W.gridSpan).Attributes(W.val).Select(a => (int?)a).FirstOrDefault();
                        if (gridSpan != null)
                            colSpan = new XAttribute("colspan", (int)gridSpan);
                    }
                    style.AddIfMissing("padding-top", "0in");
                    style.AddIfMissing("padding-bottom", "0in");

                    var cell = new XElement(Xhtml.td,
                        rowSpan,
                        colSpan,
                        CreateBorderDivs(wordDoc, settings, element.Elements()));
                    cell.AddAnnotation(style);
                    return cell;
                }

                // Transform images
                if (element.Name == W.drawing || element.Name == W.pict || element.Name == W._object)
                {
                    if (settings.ImageHandler == null)
                        return null;
                    return ProcessImage(wordDoc, element, settings.ImageHandler);
                }

                if (element.Name == W.sdt)
                {
                    var relevantAncestors = element.Ancestors().TakeWhile(a => a.Name != W.txbxContent);
                    var isRunLevelContentControl = relevantAncestors.Any(a => a.Name == W.p);
                    if (isRunLevelContentControl)
                    {
                        var o = element.Element(W.sdtContent).Elements().Select(e => ConvertToHtmlTransform(wordDoc, settings, e, false, currentMarginLeft))
                            .ToList();
                        return o;
                    }
                    else
                    {
                        var o = CreateBorderDivs(wordDoc, settings, element.Element(W.sdtContent).Elements());
                        return o;
                    }
                }

                if (element.Name == W.smartTag || element.Name == W.fldSimple)
                {
                    var o = CreateBorderDivs(wordDoc, settings, element.Elements());
                    return o;
                }

                return null;
            }
            return null;
        }
        private static XElement CharStyleRollup(FormattingAssemblerInfo fai, WordprocessingDocument wDoc, XElement runOrPara)
        {
            var sXDoc = wDoc.MainDocumentPart.StyleDefinitionsPart.GetXDocument();

            string charStyle = null;
            string paraStyle = null;
            XElement rPr = null;
            XElement pPr = null;
            XElement pStyle = null;
            XElement rStyle = null;
            CachedParaInfo cpi = null; // CachedParaInfo is an optimization for the case where a paragraph contains thousands of runs.

            if (runOrPara.Name == W.p)
            {
                cpi = runOrPara.Annotation<CachedParaInfo>();
                if (cpi != null)
                    pPr = cpi.ParagraphProperties;
                else
                {
                    pPr = runOrPara.Element(W.pPr);
                    if (pPr != null)
                    {
                        paraStyle = (string)pPr.Elements(W.pStyle).Attributes(W.val).FirstOrDefault();
                    }
                    else
                    {
                        paraStyle = fai.DefaultParagraphStyleName;
                    }
                    cpi = new CachedParaInfo
                    {
                        ParagraphProperties = pPr,
                        ParagraphStyleName = paraStyle,
                    };
                    runOrPara.AddAnnotation(cpi);
                }
                if (pPr != null)
                {
                    rPr = pPr.Element(W.rPr);
                }
            }
            else
            {
                rPr = runOrPara.Element(W.rPr);
            }
            if (rPr != null)
            {
                rStyle = rPr.Element(W.rStyle);
                if (rStyle != null)
                {
                    charStyle = (string)rStyle.Attribute(W.val);
                }
                else
                {
                    if (runOrPara.Name == W.r)
                        charStyle = (string)runOrPara
                            .Ancestors(W.p)
                            .Take(1)
                            .Elements(W.pPr)
                            .Elements(W.pStyle)
                            .Attributes(W.val)
                            .FirstOrDefault();
                    else
                        charStyle = (string)runOrPara
                            .Elements(W.pPr)
                            .Elements(W.pStyle)
                            .Attributes(W.val)
                            .FirstOrDefault();
                }
            }

            if (charStyle == null)
            {
                if (runOrPara.Name == W.r)
                {
                    var ancestorPara = runOrPara.Ancestors(W.p).First();
                    cpi = ancestorPara.Annotation<CachedParaInfo>();
                    if (cpi != null)
                        charStyle = cpi.ParagraphStyleName;
                    else
                        charStyle = (string)runOrPara.Ancestors(W.p).First().Elements(W.pPr).Elements(W.pStyle).Attributes(W.val).FirstOrDefault();
                }
                if (charStyle == null)
                {
                    charStyle = fai.DefaultParagraphStyleName;
                }
            }

            // A run always must have an ancestor paragraph.
            XElement para = null;
            var rolledUpParaStyleRunProps = new XElement(W.rPr);
            if (runOrPara.Name == W.r)
            {
                para = runOrPara.Ancestors(W.p).FirstOrDefault();
            }
            else
            {
                para = runOrPara;
            }

            cpi = para.Annotation<CachedParaInfo>();
            if (cpi != null)
            {
                pPr = cpi.ParagraphProperties;
            }
            else
            {
                pPr = para.Element(W.pPr);
            }
            if (pPr != null)
            {
                pStyle = pPr.Element(W.pStyle);
                if (pStyle != null)
                {
                    paraStyle = (string)pStyle.Attribute(W.val);
                }
                else
                {
                    paraStyle = fai.DefaultParagraphStyleName;
                }
            }
            else
                paraStyle = fai.DefaultParagraphStyleName;

            string key = (paraStyle == null ? "[null]" : paraStyle) + "~|~" +
                (charStyle == null ? "[null]" : charStyle);
            XElement rolledRunProps = null;

            if (fai.RolledCharacterStyles.ContainsKey(key))
                rolledRunProps = fai.RolledCharacterStyles[key];
            else
            {
                XElement rolledUpCharStyleRunProps = new XElement(W.rPr);
                if (charStyle != null)
                {
                    rolledUpCharStyleRunProps =
                        CharStyleStack(wDoc, charStyle)
                            .Aggregate(new XElement(W.rPr),
                                (r, s) =>
                                {
                                    var newRunProps = MergeStyleElement(s, r);
                                    return newRunProps;
                                });
                }

                if (paraStyle != null)
                {
                    rolledUpParaStyleRunProps = ParaStyleRunPropsStack(wDoc, paraStyle)
                        .Aggregate(new XElement(W.rPr),
                            (r, s) =>
                            {
                                var newCharStyleRunProps = MergeStyleElement(s, r);
                                return newCharStyleRunProps;
                            });
                }
                rolledRunProps = MergeStyleElement(rolledUpCharStyleRunProps, rolledUpParaStyleRunProps);
                fai.RolledCharacterStyles.Add(key, rolledRunProps);
            }

            return rolledRunProps;
        }
Пример #27
0
                /// <summary>
                /// Validate the behavior of annotations on Container.
                /// </summary>
                /// <param name="contextValue"></param>
                /// <returns></returns>
                //[Variation(Desc = "ContainerAnnotations")]
                public void ContainerAnnotations()
                {
                    XElement element1 = new XElement("e1");
                    XElement element2 = new XElement("e2");

                    // Check argument null exception on add.
                    try
                    {
                        element1.AddAnnotation(null);
                        Validate.ExpectedThrow(typeof(ArgumentNullException));
                    }
                    catch (Exception ex)
                    {
                        Validate.Catch(ex, typeof(ArgumentNullException));
                    }

                    // Before adding anything, should not be able to get any annotations.
                    Validate.IsNull(element1.Annotation(typeof(object)));
                    element1.RemoveAnnotations(typeof(object));
                    Validate.IsNull(element1.Annotation(typeof(object)));

                    // First annotation: 2 cases, object[] and other.
                    object obj1 = "hello";
                    element1.AddAnnotation(obj1);
                    Validate.IsNull(element1.Annotation(typeof(byte)));
                    Validate.IsReferenceEqual(element1.Annotation(typeof(string)), obj1);
                    element1.RemoveAnnotations(typeof(string));
                    Validate.IsNull(element1.Annotation(typeof(string)));

                    object[] obj2 = new object[] { 10, 20, 30 };

                    element2.AddAnnotation(obj2);
                    Validate.IsReferenceEqual(element2.Annotation(typeof(object[])), obj2);
                    Validate.Enumerator<object>((object[])element2.Annotation(typeof(object[])), new object[] { 10, 20, 30 });
                    element2.RemoveAnnotations(typeof(object[]));
                    Validate.IsNull(element2.Annotation(typeof(object[])));

                    // Single annotation; add a second one. Check that duplicates are allowed.
                    object obj3 = 10;
                    element1.AddAnnotation(obj3);
                    Validate.IsReferenceEqual(element1.Annotation(typeof(int)), obj3);
                    element1.AddAnnotation(1000);
                    element1.RemoveAnnotations(typeof(int[]));
                    Validate.IsNull(element1.Annotation(typeof(object[])));

                    object obj4 = "world";
                    element1.AddAnnotation(obj4);

                    Validate.IsReferenceEqual(element1.Annotation(typeof(int)), obj3);
                    Validate.IsReferenceEqual(element1.Annotation(typeof(string)), obj4);

                    // Multiple annotations already. Add one on the end.
                    object obj5 = 20L;
                    element1.AddAnnotation(obj5);

                    Validate.IsReferenceEqual(element1.Annotation(typeof(int)), obj3);
                    Validate.IsReferenceEqual(element1.Annotation(typeof(string)), obj4);
                    Validate.IsReferenceEqual(element1.Annotation(typeof(long)), obj5);

                    // Remove one from the middle and then add, which should use the
                    // freed slot.
                    element1.RemoveAnnotations(typeof(string));
                    Validate.IsNull(element1.Annotation(typeof(string)));

                    object obj6 = 30m;
                    element1.AddAnnotation(obj6);

                    Validate.IsReferenceEqual(element1.Annotation(typeof(int)), obj3);
                    Validate.IsReferenceEqual(element1.Annotation(typeof(long)), obj5);
                    Validate.IsReferenceEqual(element1.Annotation(typeof(decimal)), obj6);

                    // Ensure that duplicates are allowed.           
                    element1.AddAnnotation(40m);
                    Validate.IsNull(element1.Annotation(typeof(sbyte)));

                    // A couple of additional remove cases.
                    element2.AddAnnotation(obj2);
                    element2.AddAnnotation(obj3);
                    element2.AddAnnotation(obj5);
                    element2.AddAnnotation(obj6);

                    element2.RemoveAnnotations(typeof(float));
                    Validate.IsNull(element2.Annotation(typeof(float)));
                }
        private static object CreateBorderDivs(WordprocessingDocument wordDoc, HtmlConverterSettings settings, IEnumerable<XElement> elements)
        {
            return elements.GroupAdjacent(e =>
                {
                    if (e.Elements(W.pPr).Elements(W.pBdr).Any())
                    {
                        var pBdr = e.Element(W.pPr).Element(W.pBdr);
                        var indStr = "";
                        var ind = e.Element(W.pPr).Element(W.ind);
                        if (ind != null)
                            indStr = ind.ToString(SaveOptions.DisableFormatting);
                        return pBdr.ToString(SaveOptions.DisableFormatting) + indStr;
                    }
                    else if (e.Name == W.tbl)
                    {
                        return "table";
                    }
                    else
                    {
                        return ""; // empty string means no pBdr
                    }
                })
                .Select(g =>
                {
                    if (g.Key == "")
                    {
                        var o = GroupAndVerticallySpaceNumberedParagraphs(wordDoc, settings, g, 0m);
                        return (object)o;
                    }
                    if (g.Key == "table")
                    {
                        var o = g.Select(gc => ConvertToHtmlTransform(wordDoc,
                            settings, gc, false, 0));
                        return o;
                    }
                    var pPr = g.First().Element(W.pPr);
                    var pBdr = pPr.Element(W.pBdr);
                    Dictionary<string, string> style = new Dictionary<string, string>();
                    GenerateBorderStyle(pBdr, W.top, style, BorderType.Paragraph);
                    GenerateBorderStyle(pBdr, W.right, style, BorderType.Paragraph);
                    GenerateBorderStyle(pBdr, W.bottom, style, BorderType.Paragraph);
                    GenerateBorderStyle(pBdr, W.left, style, BorderType.Paragraph);
                    var ind = pPr.Element(W.ind);
                    decimal currentMarginLeft = 0m;
                    if (ind != null)
                    {
                        decimal? left = (decimal?)ind.Attribute(W.left);
                        decimal leftInInches = 0;
                        if (left != null)
                            leftInInches = (decimal)left / 1440;
                        decimal? hanging = (decimal?)ind.Attribute(W.hanging);
                        decimal hangingInInches = 0;
                        if (hanging != null)
                            hangingInInches = -(decimal)hanging / 1440;
                        currentMarginLeft = leftInInches + hangingInInches;
                        style.AddIfMissing("margin-left", string.Format("{0:0.00}in", currentMarginLeft));
                    }

                    var div = new XElement(Xhtml.div,
                        GroupAndVerticallySpaceNumberedParagraphs(wordDoc, settings, g, currentMarginLeft));

                    div.AddAnnotation(style);
                    return div;
                })
            .ToList();
        }
        /*
         * Notes on line spacing
         *
         * the w:line and w:lineRule attributes control spacing between lines - including between lines within a paragraph
         *
         * If w:spacing w:lineRule="auto" then
         *   w:spacing w:line is a percentage where 240 == 100%
         *
         *   (line value / 240) * 100 = percentage of line
         *
         * If w:spacing w:lineRule="exact" or w:lineRule="atLeast" then
         *   w:spacing w:line is in twips
         *   1440 = exactly one inch from line to line
         *
         * Handle
         * - ind
         * - jc
         * - numPr
         * - pBdr
         * - shd
         * - spacing
         * - textAlignment
         *
         * Don't Handle (yet)
         * - adjustRightInd?
         * - autoSpaceDE
         * - autoSpaceDN
         * - bidi
         * - contextualSpacing
         * - divId
         * - framePr
         * - keepLines
         * - keepNext
         * - kinsoku
         * - mirrorIndents
         * - overflowPunct
         * - pageBreakBefore
         * - snapToGrid
         * - suppressAutoHyphens
         * - suppressLineNumbers
         * - suppressOverlap
         * - tabs
         * - textBoxTightWrap
         * - textDirection
         * - topLinePunct
         * - widowControl
         * - wordWrap
         *
         */

        private static object ConvertParagraph(WordprocessingDocument wordDoc, HtmlConverterSettings settings,
            XElement paragraph, XName elementName, bool suppressTrailingWhiteSpace, decimal currentMarginLeft, bool isBidi)
        {
            var style = DefineParagraphStyle(paragraph, elementName, suppressTrailingWhiteSpace, currentMarginLeft, isBidi);
            var rtl = isBidi ? new XAttribute("dir", "rtl") : new XAttribute("dir", "ltr");
            var firstMark = isBidi ? new XEntity("#x200f") : null;

            // Analyze initial runs to see whether we have a tab, in which case we will render
            // a span with a defined width and ignore the tab rather than rendering the text
            // preceding the tab and the tab as a span with a computed width.
            var firstTabRun = paragraph
                .Elements(W.r)
                .FirstOrDefault(run => run.Elements(W.tab).Any());
            var elementsPrecedingTab = firstTabRun != null
                ? paragraph.Elements(W.r).TakeWhile(e => e != firstTabRun)
                    .Where(e => e.Elements().Any(c => c.Attributes(PtOpenXml.TabWidth).Any())).ToList()
                : Enumerable.Empty<XElement>().ToList();

            // TODO: Revisit
            // For the time being, if a hyperlink field precedes the tab, we'll render it as before.
            var hyperlinkPrecedesTab = elementsPrecedingTab
                .Elements(W.r)
                .Elements(W.instrText)
                .Select(e => e.Value)
                .Any(value => value != null && value.TrimStart().ToUpper().StartsWith("HYPERLINK"));
            if (hyperlinkPrecedesTab)
            {
                var paraElement1 = new XElement(elementName,
                    rtl,
                    firstMark,
                    ConvertContentThatCanContainFields(wordDoc, settings, paragraph.Elements()));
                paraElement1.AddAnnotation(style);
                return paraElement1;
            }

            var txElementsPrecedingTab = TransformElementsPrecedingTab(wordDoc, settings, elementsPrecedingTab, firstTabRun);
            var elementsSucceedingTab = firstTabRun != null
                ? paragraph.Elements().SkipWhile(e => e != firstTabRun).Skip(1)
                : paragraph.Elements();
            var paraElement = new XElement(elementName,
                rtl,
                firstMark,
                txElementsPrecedingTab,
                ConvertContentThatCanContainFields(wordDoc, settings, elementsSucceedingTab));
            paraElement.AddAnnotation(style);

            return paraElement;
        }
        /*
         * Notes on line spacing
         * 
         * the w:line and w:lineRule attributes control spacing between lines - including between lines within a paragraph
         * 
         * If w:spacing w:lineRule="auto" then
         *   w:spacing w:line is a percentage where 240 == 100%
         *   
         *   (line value / 240) * 100 = percentage of line 
         *   
         * If w:spacing w:lineRule="exact" or w:lineRule="atLeast" then
         *   w:spacing w:line is in twips
         *   1440 = exactly one inch from line to line
         *
         * Handle
         * - ind
         * - jc
         * - numPr
         * - pBdr
         * - shd
         * - spacing
         * - textAlignment
         *  
         * Don't Handle (yet)
         * - adjustRightInd?
         * - autoSpaceDE
         * - autoSpaceDN
         * - bidi
         * - contextualSpacing
         * - divId
         * - framePr
         * - keepLines
         * - keepNext
         * - kinsoku
         * - mirrorIndents
         * - overflowPunct
         * - pageBreakBefore
         * - snapToGrid
         * - suppressAutoHyphens
         * - suppressLineNumbers
         * - suppressOverlap
         * - tabs
         * - textBoxTightWrap
         * - textDirection
         * - topLinePunct
         * - widowControl
         * - wordWrap
         * 
         */

        private static object ConvertParagraph(WordprocessingDocument wordDoc, HtmlConverterSettings settings,
            XElement paragraph, XName elementName, bool suppressTrailingWhiteSpace, decimal currentMarginLeft, bool isBidi)
        {
            var style = new Dictionary<string, string>();
            var sn = (string)paragraph.Attribute(PtOpenXml.StyleName);
            if (sn != null)
                style.Add("PtStyleName", sn);

            XElement pPr = paragraph.Element(W.pPr);
            if (pPr != null)
            {
                var spacing = pPr.Element(W.spacing);
                if (spacing != null)
                {
                    var spacingBefore = (decimal?)spacing.Attribute(W.before);
                    if (spacingBefore != null)
                        style.AddIfMissing("margin-top", string.Format("{0}pt", spacingBefore / 20.0m));

                    var lineRule = (string)spacing.Attribute(W.lineRule);
                    if (lineRule == "auto")
                    {
                        var line = (decimal)spacing.Attribute(W.line);
                        if (line != 240m)
                        {
                            var pct = (line / 240m) * 100m;
                            style.Add("line-height", string.Format("{0:0.0}%", pct));
                        }
                    }
                    if (lineRule == "exact")
                    {
                        var line = (decimal)spacing.Attribute(W.line);
                        var points = line / 20m;
                        style.Add("line-height", string.Format("{0:0.0}pt", points));
                    }
                    if (lineRule == "atLeast")
                    {
                        var line = (decimal)spacing.Attribute(W.line);
                        var points = line / 20m;
                        if (points >= 14m)
                            style.Add("line-height", string.Format("{0:0.0}pt", points));
                    }

                    decimal? spacingAfter;
                    if (suppressTrailingWhiteSpace)
                        spacingAfter = 0;
                    else
                        spacingAfter = (decimal?)spacing.Attribute(W.after) /*+ addToSpacing*/;

                    if (spacingAfter != null)
                        style.AddIfMissing("margin-bottom", string.Format("{0}pt", spacingAfter / 20.0m));

                }

                var ind = pPr.Element(W.ind);
                if (ind != null)
                {
                    decimal? left = (decimal?)ind.Attribute(W.left);
                    if (left != null)
                    {
                        decimal leftInInches = (decimal)left / 1440 - currentMarginLeft;
                        style.AddIfMissing(isBidi ? "margin-right" : "margin-left", 
                            string.Format("{0:0.00}in", leftInInches));
                    }

                    decimal? right = (decimal?)ind.Attribute(W.right);
                    if (right != null)
                    {
                        decimal rightInInches = (decimal)right / 1440;
                        style.AddIfMissing(isBidi ? "margin-left" : "margin-right",
                            string.Format("{0:0.00}in", rightInInches));
                    }

                    decimal? firstLine = (decimal?)ind.Attribute(W.firstLine);
                    if (firstLine != null)
                    {
                        decimal firstLineInInches = (decimal)firstLine / 1440m;
                        style.AddIfMissing("text-indent", string.Format("{0:0.00}in", firstLineInInches));
                    }
                    decimal? hanging = (decimal?)ind.Attribute(W.hanging);
                    if (hanging != null)
                    {
                        decimal hangingInInches = (decimal)-hanging / 1440m;
                        style.AddIfMissing("text-indent", string.Format("{0:0.00}in", hangingInInches));
                    }
                }

                // todo need to handle
                // - both
                // - mediumKashida
                // - distribute
                // - numTab
                // - highKashida
                // - lowKashida
                // - thaiDistribute

                var jcVal = (string)pPr.Elements(W.jc).Attributes(W.val).FirstOrDefault();
                if (jcVal == null)
                {
                    jcVal = "left";
                }
                if (jcVal == "left")
                {
                    if (isBidi)
                        style.AddIfMissing("text-align", "right");
                    else
                        style.AddIfMissing("text-align", "left");
                }
                else if (jcVal == "right")
                {
                    if (isBidi)
                        style.AddIfMissing("text-align", "left");
                    else
                        style.AddIfMissing("text-align", "right");
                }
                else if (jcVal == "center")
                    style.AddIfMissing("text-align", "center");
                else if (jcVal == "both")
                    style.AddIfMissing("text-align", "justify");

                CreateStyleFromShd(style, pPr.Element(W.shd));

                // Pt.FontName
                string font = (string)paragraph.Attributes(PtOpenXml.FontName).FirstOrDefault();
                if (font != null)
                    CreateFontCssProperty(font, style);

                // W.sz
                decimal? sz = null;

                var languageType = (string)paragraph.Attribute(PtOpenXml.LanguageType);
                if (languageType == "bidi")
                    sz = (decimal?)pPr.Elements(W.rPr).Elements(W.szCs).Attributes(W.val).FirstOrDefault();
                else
                    sz = (decimal?)pPr.Elements(W.rPr).Elements(W.sz).Attributes(W.val).FirstOrDefault();

                var sizesOfAllRunsInParagraph = paragraph
                    .DescendantsTrimmed(W.txbxContent)
                    .Select(run =>
                    {
                        if (run.Name != W.r)
                            return null;
                        var runLanguageType = (string)run.Attribute(PtOpenXml.LanguageType);
                        if (runLanguageType == "bidi")
                        {
                            var runCsSz = (decimal?)run
                                .Elements(W.rPr)
                                .Elements(W.szCs)
                                .Attributes(W.val)
                                .FirstOrDefault();
                            return runCsSz;
                        }
                        else
                        {
                            var runSz = (decimal?)run
                                .Elements(W.rPr)
                                .Elements(W.sz)
                                .Attributes(W.val)
                                .FirstOrDefault();
                            return runSz;
                        }
                    })
                    .Where(runSz => runSz != null);

                if (sizesOfAllRunsInParagraph.Any())
                    sz = sizesOfAllRunsInParagraph.Cast<decimal>().Max();

                if (sz != null)
                    style.AddIfMissing("font-size", string.Format("{0}pt", sz / 2.0m));

                var languageTypeOfAllRunsInParagraph = paragraph
                    .DescendantsTrimmed(W.txbxContent)
                    .Select(run =>
                    {
                        if (run.Name != W.r)
                            return null;
                        var runLanguageType = (string)run.Attribute(PtOpenXml.LanguageType);
                        return runLanguageType;
                    })
                    .Where(runSz => runSz != null);

                if (!languageTypeOfAllRunsInParagraph.Any(lt => lt == "bidi"))
                    style.AddIfMissing("line-height", "108%");

                // vertical text alignment as of December 2013 does not work in any major browsers.
                var verticalTextAlignment = (string)pPr.Elements(W.textAlignment).Attributes(W.val).FirstOrDefault();
                if (verticalTextAlignment != null && verticalTextAlignment != "auto")
                {
                    if (verticalTextAlignment == "top")
                        style.AddIfMissing("vertical-align", "top");
                    else if (verticalTextAlignment == "center")
                        style.AddIfMissing("vertical-align", "middle");
                    else if (verticalTextAlignment == "baseline")
                        style.AddIfMissing("vertical-align", "baseline");
                    else if (verticalTextAlignment == "bottom")
                        style.AddIfMissing("vertical-align", "bottom");
                }

                style.AddIfMissing("margin-top", "0pt");
                style.AddIfMissing("margin-left", "0pt");
                style.AddIfMissing("margin-right", "0pt");
                style.AddIfMissing("margin-bottom", ".001pt");

            }
            XAttribute rtl = null;
            XEntity firstMark = null;
            if (isBidi)
            {
                rtl = new XAttribute("dir", "rtl");
                firstMark = new XEntity("#x200f"); // RLM
            }
            else
            {
                rtl = new XAttribute("dir", "ltr");
            }
            var paraElement = new XElement(elementName,
                rtl,
                firstMark,
                ConvertContentThatCanContainFields(wordDoc, settings, paragraph.Elements()));
            paraElement.AddAnnotation(style);
            return paraElement;
        }
		public BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent) {
			var record = (OptimizedStaticResourceRecord)((BamlRecordNode)node).Record;
			var bamlElem = new BamlElement(node);
			object key;
			if (record.IsType) {
				var value = ctx.ResolveType(record.ValueId);

				var typeElem = new XElement(ctx.GetXamlNsName("TypeExtension", parent.Xaml));
				typeElem.AddAnnotation(ctx.ResolveType(0xfd4d)); // Known type - TypeExtension
				typeElem.Add(new XElement(ctx.GetPseudoName("Ctor"), ctx.ToString(parent.Xaml, value)));
				key = typeElem;
			}
			else if (record.IsStatic) {
				string attrName;
				if (record.ValueId > 0x7fff) {
					bool isKey = true;
					short bamlId = (short)-record.ValueId;
					if (bamlId > 232 && bamlId < 464) {
						bamlId -= 232;
						isKey = false;
					}
					else if (bamlId > 464 && bamlId < 467) {
						bamlId -= 231;
					}
					else if (bamlId > 467 && bamlId < 470) {
						bamlId -= 234;
						isKey = false;
					}
					var res = ctx.Baml.KnownThings.Resources(bamlId);
					string name;
					if (isKey)
						name = res.Item1 + "." + res.Item2;
					else
						name = res.Item1 + "." + res.Item3;
					var xmlns = ctx.GetXmlNamespace("http://schemas.microsoft.com/winfx/2006/xaml/presentation");
					attrName = ctx.ToString(parent.Xaml, xmlns.GetName(name));
				}
				else {
					var value = ctx.ResolveProperty(record.ValueId);

					value.DeclaringType.ResolveNamespace(parent.Xaml, ctx);
					var xName = value.ToXName(ctx, parent.Xaml);

					attrName = ctx.ToString(parent.Xaml, xName);
				}

				var staticElem = new XElement(ctx.GetXamlNsName("StaticExtension", parent.Xaml));
				staticElem.AddAnnotation(ctx.ResolveType(0xfda6)); // Known type - StaticExtension
				staticElem.Add(new XElement(ctx.GetPseudoName("Ctor"), attrName));
				key = staticElem;
			}
			else
				key = ctx.ResolveString(record.ValueId);

			var extType = ctx.ResolveType(0xfda5);
			var resElem = new XElement(extType.ToXName(ctx));
			resElem.AddAnnotation(extType); // Known type - StaticResourceExtension
			bamlElem.Xaml = resElem;
			parent.Xaml.Element.Add(resElem);

			var attrElem = new XElement(ctx.GetPseudoName("Ctor"));
			attrElem.Add(key);
			resElem.Add(attrElem);

			return bamlElem;
		}