// Parse the chapters in the document, recursively
        private void ParseBookMapChapters()
        {
            List <DitaElement> chapters = RootMap.RootElement.FindChildren(_chapterElements);

            foreach (DitaElement chapter in chapters)
            {
                // What is the href to the chapter?
                string chapterHref = chapter.Attributes?["href"];

                // Try to find this file
                DitaFile linkedFile = Collection.GetFileByName(chapterHref);
                List <DitaCollectionLinkJson> children = ParseChaptersFromFile(linkedFile);
                Chapters.AddRange(children);

                if (linkedFile is DitaFileTopicAbstract && children.Count > 0)
                {
                    children[0].Children.AddRange(ParseRefs(chapter.FindChildren(_refElements)));
                }

                //if (chapter.Type == "appendices" && children.Count > 0)
                //{

                //}
            }
        }
Exemple #2
0
        // Rename the files in the collection to match their title (instead of their given file names)
        public void RenameFiles()
        {
            List <string> fileNames = new List <string>();

            // Generate a new name for each file, based on it's title
            foreach (DitaFile file in Files)
            {
                string newFileName = DitaFile.TitleToFileName(file.Title, Path.GetExtension(file.FileName));
                if (!string.IsNullOrWhiteSpace(newFileName))
                {
                    if (fileNames.Contains(newFileName))
                    {
                        string newFileNameBase = newFileName;
                        int    counter         = 1;
                        while (fileNames.Contains(newFileName))
                        {
                            newFileName = Path.ChangeExtension($"{Path.GetFileNameWithoutExtension(newFileNameBase)}_{counter}", Path.GetExtension(newFileNameBase));
                            counter++;
                        }
                    }

                    fileNames.Add(newFileName);
                    file.NewFileName = newFileName;
                    Trace.TraceInformation($"Renaming {file.FileName} to {newFileName}");
                }
            }

            // Update references from old to new file names
            UpdateRenamedFileReferences();
        }
Exemple #3
0
        // Load a single file
        private DitaFile LoadFile(string filePath)
        {
            // Look for known extensions
            // Is this an image?
            if (Path.HasExtension(filePath))
            {
                string extension = Path.GetExtension(filePath)?.ToLower();
                if (DitaFileImage.Extensions.Contains(extension))
                {
                    DitaFileImage image = new DitaFileImage(filePath);
                    Trace.TraceInformation($"{Path.GetFileName(filePath)} is a {typeof(DitaFileImage)}");
                    return(image);
                }
            }

            // Try to load the given file

            try {
                // Try to load as an XML document
                XmlDocument xmlDocument = DitaFile.LoadAndCheckType(filePath, out Type fileType);

                // Create a new object of the correct type
                if (DitaFile.DitaFileTypeCreation.ContainsKey(fileType))
                {
                    return(DitaFile.DitaFileTypeCreation[fileType](xmlDocument, filePath));
                }
            }
            catch (Exception ex) {
                Trace.TraceWarning($"Unable to load {filePath} as XML: {ex}");
            }

            throw new Exception($"{filePath} is an unknown file type.");
        }
Exemple #4
0
        // Loads all of the DITA files and supports from the given directory
        private void LoadDirectory(string input)
        {
            // Get a list of all the files in the directory
            string[] files = Directory.GetFiles(input);
            if (files.Length > 0)
            {
                Trace.TraceInformation($"Checking {files.Length} files...");

                foreach (string file in files)
                {
                    try {
                        DitaFile ditaFile = LoadFile(file);
                        Files.Add(ditaFile);
                    }
                    catch {
                        Trace.TraceWarning($"Unable to load file {file}");
                    }
                }

                Trace.TraceInformation($"Found {FileCount} valid DITA files.");
                Trace.TraceInformation($"- {GetBookMaps().Count} bookmaps.");
                Trace.TraceInformation($"- {GetMaps().Count} maps.");
                Trace.TraceInformation($"- {GetTopics().Count} topics.");
                Trace.TraceInformation($"- {GetImages().Count} images.");
            }
            else
            {
                Trace.TraceWarning($"No files found in directory {input}");
            }
        }
Exemple #5
0
        // Construct from a single topic
        public DitaPageJson(DitaFile file, DitaCollection collection)
        {
            Collection = collection;

            // Get the title of the page
            Title = DitaFile.FixSpecialCharacters(file.Title);

            // Create the file name
            FileName = file.NewFileName ?? file.FileName;
            FileName = Path.ChangeExtension(FileName, ".json");

            OriginalFileName = file.FileName;

            // Find the body element
            string bodyElementName = null;

            if (DitaFile.DitaFileBodyElement.ContainsKey(file.GetType()))
            {
                bodyElementName = DitaFile.DitaFileBodyElement[file.GetType()]();
            }

            if (!string.IsNullOrEmpty(bodyElementName))
            {
                DitaElement bodyElement = file.RootElement.FindOnlyChild(bodyElementName);

                if (bodyElement != null)
                {
                    Sections = new List <DitaPageSectionJson>();

                    // Convert the body to html
                    DitaElementToHtmlConverter htmlConverter = new DitaElementToHtmlConverter(collection);
                    htmlConverter.Convert(bodyElement, Sections, file.FileName, out string bodyHtml);
                    BodyHtml = bodyHtml;

                    // Convert the body to text
                    DitaElementToTextConverter textConverter = new DitaElementToTextConverter();
                    textConverter.Convert(bodyElement, out string bodyText);
                    BodyText = bodyText;
                }
                else
                {
                    Trace.TraceWarning($"Body element not found in {file.FileName}.");
                }
            }
            else
            {
                Trace.TraceWarning($"No body element identified in {file.FileName}.");
            }

            IsEmpty = string.IsNullOrEmpty(BodyText) || string.IsNullOrEmpty(Title);
        }
        // Parse chapter structure from a dita file
        private List <DitaCollectionLinkJson> ParseChaptersFromFile(DitaFile linkedFile, string navTitle = null)
        {
            Trace.TraceInformation($"Converting {linkedFile}");

            // What type of file is this?
            switch (linkedFile)
            {
            case DitaFileBookMap bookMap:
                // This should never happen
                throw new Exception($"Found bookmap {linkedFile} nested in bookmap.");

            case DitaFileMap map:
                return(ParseChaptersFromMap(map));

            case DitaFileTopicAbstract topic:
                return(ParseChaptersFromTopic(topic, navTitle));
            }

            return(null);
        }
        // Construct a collection from a Dita bookmap in a Dita collection
        public DitaCollectionJson(DitaCollection collection, DitaFile rootMap)
        {
            // Store the construction properties
            Collection = collection;
            RootMap    = rootMap;

            // Initialize the properties
            BookTitle = new Dictionary <string, string>();
            BookMeta  = new Dictionary <string, string>();
            Chapters  = new List <DitaCollectionLinkJson>();
            Pages     = new List <DitaPageJson>();

            // Create the output object
            if (RootMap is DitaFileBookMap)
            {
                ParseBookMap();
            }
            else if (RootMap is DitaFileMap)
            {
                ParseMap();
            }
        }
Exemple #8
0
        // Try to find the root map file
        private void FindRootMap(string rootMapFile)
        {
            // If no file name specified, try to find a bookmap
            if (string.IsNullOrEmpty(rootMapFile))
            {
                List <DitaFileBookMap> bookMaps = Collection.GetBookMaps();
                if (bookMaps.Count == 1)
                {
                    RootMap = bookMaps[0];
                    return;
                }
                throw new Exception($"Expecting exactly 1 bookmap, but found {bookMaps.Count}");
            }

            // Is there a bookmap or map with the given name?
            DitaFile rootFile = Collection.GetFileByName(rootMapFile);

            if (rootFile == null)
            {
                throw new Exception($"Specified root map file {rootMapFile} was not found in collection.");
            }

            switch (rootFile)
            {
            case DitaFileBookMap bookMap:
                RootMap = bookMap;
                break;

            case DitaFileMap map:
                RootMap = map;
                break;

            default:
                throw new Exception($"{rootMapFile} must be a map or bookmap.");
            }
        }
Exemple #9
0
        // 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);
                    }
                }
            }
        }
Exemple #10
0
        // 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("#");
        }
        private List <DitaCollectionLinkJson> ParseRefs(List <DitaElement> topicRefElements)
        {
            List <DitaCollectionLinkJson> chapters = new List <DitaCollectionLinkJson>();

            if (topicRefElements?.Count > 0)
            {
                foreach (DitaElement topicRefElement in topicRefElements)
                {
                    // Try to find the linked file
                    string topicRefHref     = topicRefElement.AttributeValueOrDefault("href", "");
                    string topicRefKeyRef   = topicRefElement.AttributeValueOrDefault("keyref", "");
                    string topicRefNavTitle = topicRefElement?.FindOnlyChild("topicmeta")?.FindOnlyChild("navtitle")?.ToString();

                    // If there is no navtitle, check the topicmeta
                    if (string.IsNullOrWhiteSpace(topicRefNavTitle))
                    {
                        topicRefNavTitle = topicRefElement.AttributeValueOrDefault("navtitle", "");
                    }

                    // Is this an external link?
                    if (topicRefElement.AttributeValueOrDefault("scope", "") == "external")
                    {
                        DitaCollectionLinkJson externalLink = new DitaCollectionLinkJson
                        {
                            FileName   = topicRefHref,
                            Title      = topicRefNavTitle,
                            IsExternal = true
                        };
                        chapters.Add(externalLink);
                    }
                    else
                    {
                        // Local scope
                        DitaFile linkedFile = null;
                        if (!string.IsNullOrWhiteSpace(topicRefHref))
                        {
                            linkedFile = Collection.GetFileByName(topicRefHref);
                        }

                        // If no href, try to find by keyref
                        if (linkedFile == null && !string.IsNullOrWhiteSpace(topicRefKeyRef))
                        {
                            linkedFile = Collection.GetFileByKey(topicRefKeyRef);
                        }

                        if (linkedFile != null)
                        {
                            if (string.IsNullOrWhiteSpace(linkedFile.Title))
                            {
                                linkedFile.Title = topicRefNavTitle;
                            }
                            else if (string.IsNullOrWhiteSpace(topicRefNavTitle))
                            {
                                topicRefNavTitle = linkedFile.Title;
                            }

                            // Add references from the linked files
                            List <DitaCollectionLinkJson> newChapters = ParseChaptersFromFile(linkedFile, topicRefNavTitle);

                            if (newChapters != null && newChapters.Count > 0)
                            {
                                // Are there child chapters?
                                List <DitaCollectionLinkJson> childChapters = ParseRefs(topicRefElement.FindChildren(_refElements));

                                if (newChapters.Count > 1 && childChapters.Count > 0)
                                {
                                    // This should never happen
                                    throw new Exception("Found multiple children in a map and topic refs.");
                                }

                                if (childChapters != null && childChapters.Count > 0)
                                {
                                    newChapters[0]?.Children?.AddRange(childChapters);
                                }

                                chapters.AddRange(newChapters);
                            }
                        }
                        else
                        {
                            Trace.TraceWarning($"Reference with missing href/keyref: {topicRefElement}");
                        }
                    }
                }
            }

            return(chapters);
        }