Example #1
0
 private IEnumerable <string> GetManifestHtmls(Manifest manifest)
 {
     return(from file in manifest.Files
            where file != null && IsType(file, ManifestItemType.Content)
            let outputPath = ManifestUtility.GetRelativePath(file, OutputType.Html)
                             where !string.IsNullOrEmpty(outputPath)
                             select outputPath);
 }
Example #2
0
        public UrlCache(string basePath, ManifestItem[] manifestItemWithAssetIds)
        {
            Guard.ArgumentNotNullOrEmpty(basePath, nameof(basePath));
            Guard.ArgumentNotNull(manifestItemWithAssetIds, nameof(manifestItemWithAssetIds));

            _cache = new Dictionary <string, ManifestItem>();
            foreach (var item in manifestItemWithAssetIds)
            {
                string relativePath = ManifestUtility.GetRelativePath(item, OutputType.Html);
                if (!string.IsNullOrEmpty(relativePath) && relativePath.EndsWith(BuildToolConstants.OutputFileExtensions.ContentHtmlExtension, StringComparison.OrdinalIgnoreCase))
                {
                    var fullPath = PdfHelper.NormalizeFileLocalPath(basePath, relativePath);
                    if (!string.IsNullOrEmpty(fullPath) && !_cache.ContainsKey(fullPath))
                    {
                        _cache.Add(fullPath, item);
                    }
                }
            }
        }
Example #3
0
        private void ConvertCore(string basePath)
        {
            Logger.LogVerbose($"Reading files from {basePath}");
            HtmlTransformer(basePath);
            var manifest = JsonUtility.Deserialize <Manifest>(Path.Combine(basePath, ManifestConstants.ManifestFileName));

            if (manifest == null)
            {
                Logger.LogError("Manifest file is not found.");
                throw new FileNotFoundException("Manifest file is not found.");
            }

            if (manifest.Files == null || manifest.Files.Count == 0)
            {
                Logger.LogWarning($"There is no file in manifest under {_pdfOptions.SourceDirectory}");
                return;
            }

            var tocFiles = FindTocInManifest(manifest);

            if (tocFiles.Count > 0)
            {
                Logger.LogVerbose($"Found {tocFiles.Count} TOC.json files, will generate pdf.");
            }
            else
            {
                Logger.LogWarning("No TOC file is included, no PDF file will be generated.");
                return;
            }

            var tocHtmls = new ConcurrentBag <string>();

            IDictionary <string, PdfInformation> pdfInformations = new ConcurrentDictionary <string, PdfInformation>();

            var manifestItems    = manifest.Files.Where(f => IsType(f, ManifestItemType.Content)).ToArray();
            var manifestUrlCache = new UrlCache(basePath, manifestItems);

            Parallel.ForEach(
                tocFiles,
                new ParallelOptions {
                MaxDegreeOfParallelism = _pdfOptions.PdfConvertParallelism
            },
                tocFile =>
            {
                var tocJson    = ManifestUtility.GetRelativePath(tocFile, OutputType.TocJson);
                var tocAssetId = ManifestUtility.GetAssetId(tocFile);
                try
                {
                    Logger.LogVerbose($"Starting to handle {tocJson}.");
                    var tocFilePath     = NormalizeFilePath(tocJson);
                    var tocPageFilePath = Path.Combine(basePath, Path.GetDirectoryName(tocFilePath), TocPageFileName);
                    var tocModels       = LoadTocModels(basePath, tocFile) ?? new List <TocModel>();

                    var currentTocHtmls = new ConcurrentBag <string>();
                    var htmlModels      = BuildHtmlModels(basePath, tocModels, currentTocHtmls);

                    HtmlNotInTocTransformer(basePath, manifestUrlCache, currentTocHtmls);

                    if (_pdfOptions.GenerateAppendices)
                    {
                        currentTocHtmls.AsParallel().ForAll(tocHtmls.Add);
                    }

                    if (File.Exists(tocPageFilePath))
                    {
                        RemoveQueryStringAndBookmarkTransformer(tocPageFilePath);
                        AbsolutePathInTocPageFileTransformer(tocPageFilePath);
                        htmlModels.Insert(0, new HtmlModel {
                            Title = _pdfOptions.TocTitle, HtmlFilePath = tocPageFilePath
                        });
                    }

                    var coverPage = FindSiblingCoverPageInManifest(manifest, tocFile);
                    if (coverPage != null)
                    {
                        var coverPageHtmlRelativeFilePath = coverPage.OutputFiles[".html"].RelativePath;
                        var coverPageHtmlFilePath         = Path.Combine(basePath, coverPageHtmlRelativeFilePath);
                        if (File.Exists(coverPageHtmlFilePath))
                        {
                            htmlModels.Insert(0, new HtmlModel {
                                Title = _pdfOptions.CoverPageTitle, HtmlFilePath = coverPageHtmlFilePath
                            });
                        }
                    }

                    if (_pdfOptions.ExcludeTocs == null || _pdfOptions.ExcludeTocs.All(p => NormalizeFilePath(p) != tocFilePath))
                    {
                        var pdfNameFragments = new List <string> {
                            _pdfOptions.PdfDocsetName
                        };
                        if (!string.IsNullOrEmpty(_pdfOptions.Locale))
                        {
                            pdfNameFragments.Add(_pdfOptions.Locale);
                        }

                        // TODO: not consistent with OPS logic Path.ChangeExtension(tocAssetId, FileExtensions.PdfExtension).Replace('/', '_')
                        // TODO: need to update the logic in OPS when merging with OPS
                        if (!string.IsNullOrWhiteSpace(tocAssetId))
                        {
                            var subFolder = Path.GetDirectoryName(tocAssetId);
                            if (!string.IsNullOrEmpty(subFolder))
                            {
                                pdfNameFragments.Add(subFolder.Replace('/', '_'));
                            }
                        }

                        var pdfName = pdfNameFragments.ToDelimitedString("_") + FileExtensions.PdfExtension;
                        ConvertCore(basePath, pdfName, htmlModels);
                        Logger.LogInfo($"{pdfName} is generated based on {tocJson} under folder {_pdfOptions.DestDirectory}");
                        pdfInformations.Add(
                            pdfName,
                            new PdfInformation
                        {
                            DocsetName = _pdfOptions.PdfDocsetName,
                            TocFiles   = new string[] { tocFile.SourceRelativePath },
                            Version    = tocFile.Group,
                            AssetId    = tocAssetId,
                        });
                    }
                    else
                    {
                        Logger.LogVerbose($"Skipped to convert {tocJson} to pdf because of custom exclude tocs.");
                    }
                    Logger.LogVerbose($"Finished to handle {tocJson}.");
                }
                catch (Exception ex)
                {
                    Logger.LogError($"Error happen when converting {tocJson} to Pdf. Details: {ex.ToString()}");
                }
            });

            using (var fileStream = new FileStream(Path.Combine(_pdfOptions.DestDirectory, _pdfOptions.PdfDocsetName + FileExtensions.JsonExtension), FileMode.Create, FileAccess.Write))
            {
                using var ws = new StreamWriter(fileStream);
                JsonUtility.Serialize(ws, pdfInformations);
            }

            if (_pdfOptions.GenerateAppendices)
            {
                var otherConceptuals = ManifestHtmlsExceptTocHtmls(manifest, tocHtmls);
                if (otherConceptuals.Count > 0)
                {
                    var htmlModels = new List <HtmlModel>();
                    var htmlModel  = new HtmlModel
                    {
                        Title    = "appendices",
                        Children = otherConceptuals.Select((other, index) => new HtmlModel
                        {
                            Title        = $"Appendix {index + 1}",
                            HtmlFilePath = other
                        }).ToList()
                    };
                    htmlModels.Add(htmlModel);
                    Logger.LogVerbose("Starting to convert appendices to pdf.");
                    ConvertCore(basePath, "appendices", htmlModels);
                }
            }
            else
            {
                Logger.LogVerbose("Skipped to convert appendices to pdf.");
            }
        }
Example #4
0
 private bool IsType(ManifestItem item, ManifestItemType targetType)
 {
     return(ManifestUtility.GetDocumentType(item) == targetType);
 }
Example #5
0
 private IList <TocModel> LoadTocModels(string basePath, ManifestItem tocFile)
 {
     return(JsonUtility.Deserialize <IList <TocModel> >(Path.Combine(basePath, ManifestUtility.GetRelativePath(tocFile, OutputType.TocJson))));
 }