// Build a dictionary of elements in the document, by id private void ParseElementIds(DitaElement parentElement) { if (parentElement != null) { // Does this element have an id? string id = parentElement.AttributeValueOrDefault("id", string.Empty); if (!string.IsNullOrEmpty(id)) { if (!ElementsById.ContainsKey(id)) { ElementsById.Add(id, parentElement); } else { Trace.TraceWarning($"Duplicate element id {id} found in {FileName}."); } } // Parse the children if (parentElement.Children != null) { foreach (DitaElement childElement in parentElement.Children) { ParseElementIds(childElement); } } } }
private void ResolveKeywords(DitaElement parentElement, DitaCollection collection) { if (parentElement != null) { if (parentElement.Type == "keyword") { string keyref = parentElement.AttributeValueOrDefault("keyref", String.Empty); if (!string.IsNullOrWhiteSpace(keyref)) { // Try to find the referred to file DitaKeyDef keyDef = collection.GetKeyDefByKey(keyref); if (keyDef != null) { if (!string.IsNullOrWhiteSpace(keyDef.Keywords)) { parentElement.SetInnerText(keyDef.Keywords); } } } } else { // Check the child elements if (parentElement.Children != null) { foreach (DitaElement childElement in parentElement.Children) { ResolveKeywords(childElement, collection); } } } } }
// Wraps a dita element in another dita element, if needed to output correct html // For instance, wrap tables, sections, figures, etc in an <a name="..."> for instance private DitaElement PrependDitaElementIfNeeded(DitaElement inputElement) { string id = inputElement.AttributeValueOrDefault("id", null); // If this object has an id, wrap it in an a, name if (!string.IsNullOrEmpty(id)) { DitaElement outputElement = new DitaElement("a", false, null, inputElement.Parent, inputElement.PreviousSibling); outputElement.Attributes.Add("name", id); return(outputElement); } return(null); }
// Does a given image element refer to SVG? private bool IsImageElementSvg(DitaElement imageElement) { if (imageElement != null) { if (imageElement.Type == "image") { string extension = Path.GetExtension(imageElement.AttributeValueOrDefault("href", "")); if ((extension?.Equals(".svg", StringComparison.OrdinalIgnoreCase) ?? false) || (extension?.Equals(".image", StringComparison.OrdinalIgnoreCase) ?? false)) { return(true); } } } return(false); }
// Resolves conrefs in this file private void ResolveConRefs(DitaElement parentElement, DitaCollection collection) { if (parentElement != null) { bool updated = false; // Does this element have a conref? string conref = parentElement.AttributeValueOrDefault("conref", String.Empty); if (!string.IsNullOrEmpty(conref)) { // We expect the conref to be in the form of filename.xml#fileid/elementid Regex conRefRegex = new Regex("^(.*)#(.*)/(.*)$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); MatchCollection conRefMatchCollection = conRefRegex.Matches(conref); if (conRefMatchCollection?.Count > 0 && (conRefMatchCollection[0].Groups.Count == 4)) { // Extract the components of the conref string refFileName = conRefMatchCollection[0].Groups[1].Value; string refFileId = conRefMatchCollection[0].Groups[2].Value; string refElementId = conRefMatchCollection[0].Groups[3].Value; if (Path.GetFileNameWithoutExtension(refFileName) != refFileId) { Trace.TraceWarning($"conref file name '{refFileName}' is not equal to file id '{refFileId}'."); } // Try to find the file that this conref refers to DitaFile refFile = collection.GetFileByName(refFileName); if (refFile != null) { // Does the references element exist in this file if (refFile.ElementsById.ContainsKey(refElementId)) { DitaElement refElement = refFile.ElementsById[refElementId]; // Copy the refernce element parentElement.Copy(refElement); updated = true; } else { Trace.TraceWarning($"Element '{refElementId}' not found in file '{refFileName}'."); } } else { Trace.TraceWarning($"Can't find file '{refFileName}' referenced in file '{FileName}'."); } } else { Trace.TraceWarning($"conref {conref} not in expected format."); } } // Update child references if (!updated && parentElement.Children != null) { foreach (DitaElement childElement in parentElement.Children) { ResolveConRefs(childElement, collection); } } } }
// Returns the relative or absolute url from a Dita XREF for use in an html A tag private string UrlFromXref(DitaElement xrefElement, out string title) { // What is the scope string scope = xrefElement.AttributeValueOrDefault("scope", null); string format = xrefElement.AttributeValueOrDefault("format", null); string href = xrefElement.AttributeValueOrDefault("href", null); title = null; if (scope == "external") { return(href); } if (!string.IsNullOrEmpty(href)) { string result = null; if (href[0] == '#') { // Link to the same page if (href.Contains('/')) { string[] anchorSplit = href.Split('/'); if (anchorSplit.Length > 1) { result = $"#{anchorSplit[1]}"; } } else { result = href.Substring(1); } } else if (href.ToLowerInvariant().StartsWith("http")) { result = href; } else { // Split by hash, if any string[] hashSplit = href.Split('#'); // Try to find the topic it is linking to DitaFile referenceFile = Collection?.GetFileByName(hashSplit[0]); if (referenceFile != null) { result = $"%DOCUMENT_ROOT%/{Path.GetFileNameWithoutExtension(referenceFile.NewFileName)}"; if (hashSplit.Length > 1) { result += $"#{hashSplit[1]}"; } title = referenceFile.Title; } else { Trace.TraceError($"Xref refers to unknown local file {hashSplit[0]} in {FileName}"); } } if (!string.IsNullOrEmpty(result)) { return(result); } else { return("#"); } } Trace.TraceWarning($"Unknown xref scope={scope}, format={format}, href={href} in {FileName}"); return("#"); }
// Takes a DITA "tag" and returns the corresponding HTML tag private string ConvertDitaTagToHtmlTag(DitaElement element) { switch (element.Type) { case "b": return("strong"); case "colspec": TableColumnIndex++; FixUpTableColumnSpecs(); _tableColumnSpecs[TableColumnIndex] = new DitaTableColumnSpec { Number = (TableColumnIndex + 1) }; return(""); case "entry": TableRowColumnIndex++; if (element.Parent?.Parent?.Type == "thead" || element.AttributeValueOrDefault("class", "") == "th") { return("th"); } return("td"); case "fig": return("figure"); case "image": // Is this referring to an SVG or other type of image? if (IsImageElementSvg(element)) { return("object"); } return("img"); case "keyword": return(""); case "row": TableRowColumnIndex = -1; return("tr"); case "steps": return("ol"); case "step": return("li"); case "table": TableColumnIndex = -1; _tableColumnSpecs = null; break; case "tgroup": TableColumnIndex = -1; _tableColumnSpecs = null; return(""); case "title": if (element.Parent?.Type == "section") { // Create a reference to this section, if this is the title of the section if (CurrentSection != null) { if (string.IsNullOrEmpty(CurrentSection.Title) && !string.IsNullOrEmpty(CurrentSection.Anchor)) { CurrentSection.Title = element.ToString(); Sections.Add(CurrentSection); CurrentSection = null; } } return("h3"); } return("h4"); case "xref": return("a"); case "#text": return(""); } return(element.Type); }