/
diev
/
FransBouma-DocNet
Обзор
Документация
Войти
/
diev
/
FransBouma-DocNet
Код
Запросы
0
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/DocNet/Config.cs
385 строк
11 KB
Frans Bouma
Fixes #92
29 ноя 2023, 16:20
29 ноя 2023, 16:20
0f88724
Код
Авторство
О чём код?
////////////////////////////////////////////////////////////////////////////////////////////// // DocNet is licensed under the MIT License (MIT) // Copyright(c) 2016 Frans Bouma // Get your copy at: https://github.com/FransBouma/DocNet // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in the // Software without restriction, including without limitation the rights to use, copy, // modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, // and to permit persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included in all copies // or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////////////////////// using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using Newtonsoft.Json.Linq; namespace Docnet { public class Config { #region Members private string _configFileSourcePath, _templateContents, _docsSourcePath, _destinationPath, _themeFolder; private dynamic _configData; private NavigationLevel _pages; #endregion internal bool Load(string configFile) { _configFileSourcePath = Path.GetDirectoryName(configFile); var configData = File.ReadAllText(configFile, Encoding.UTF8); if(string.IsNullOrWhiteSpace(configData)) { Console.WriteLine("[ERROR] '{0}' is empty.", configFile); return false; } _configData = JObject.Parse(configData); if(_configData == null) { Console.WriteLine("[ERROR] Parsing '{0}' failed!", configFile); return false; } if(string.IsNullOrWhiteSpace(this.ThemeFolder) || !Directory.Exists(this.ThemeFolder)) { Console.WriteLine("[ERROR] Theme '{0}' or Themes folder not found.", this.ThemeFolder); return false; } _templateContents = File.ReadAllText(this.PageTemplateFile, Encoding.UTF8); if(string.IsNullOrWhiteSpace(_templateContents)) { Console.WriteLine("[ERROR] Page template '{0}' is empty.", _configData.PageTemplate); return false; } return true; } /// <summary> /// Generates the search data, which is the json file called 'search_index.json' with search data of all pages as well as the docnet_search.htm file in the output. /// The search index is written to the root of the output folder. /// </summary> /// <param name="navigationContext">The navigation context.</param> internal void GenerateSearchData(NavigationContext navigationContext) { GenerateSearchPage(navigationContext); GenerateSearchDataIndex(navigationContext); } internal void CopyThemeToDestination() { var sourceFolder = Path.Combine(this.ThemeFolder, "Destination"); if(!Directory.Exists(sourceFolder)) { Console.WriteLine("[WARNING] No theme content found! 'Destination' folder in theme folder '{0}' is missing.", this.ThemeFolder); return; } Utils.DirectoryCopy(sourceFolder, this.Destination, copySubFolders:true); } internal void CopySourceFoldersToCopy() { var foldersToCopy = this.SourceFoldersToCopy; foreach(var folder in foldersToCopy) { if(string.IsNullOrWhiteSpace(folder)) { continue; } var sourceFolderName = Path.Combine(this.Source, folder); if(!Directory.Exists(sourceFolderName)) { continue; } var destinationFolderName = Path.Combine(this.Destination, folder); Console.WriteLine("... copying '{0}' to {1}", sourceFolderName, destinationFolderName); Utils.DirectoryCopy(sourceFolderName, destinationFolderName, copySubFolders:true); } } internal void Generate404Page(NavigationContext navigationContext) { var simpleNavigationElement = new NotFoundNavigationElement { ParentContainer = Pages }; var navigatedPath = new NavigatedPath(); navigatedPath.Push(this.Pages); simpleNavigationElement.GenerateOutput(this, navigatedPath, navigationContext); navigatedPath.Pop(); } internal void ClearDestinationFolder() { if(string.IsNullOrWhiteSpace(this.Destination)) { Console.WriteLine("[WARNING] Destination is empty. No folder to clear."); return; } if(!Directory.Exists(this.Destination)) { return; } Directory.Delete(this.Destination, true); Directory.CreateDirectory(this.Destination); } /// <summary> /// Generates the index of the search data. this is a json file with per page which has markdown a couple of data elements. /// </summary> private void GenerateSearchDataIndex(NavigationContext navigationContext) { var collectedSearchEntries = new List<SearchIndexEntry>(); this.Pages.CollectSearchIndexEntries(collectedSearchEntries, new NavigatedPath(), navigationContext); JObject searchIndex = new JObject(new JProperty("docs", new JArray( collectedSearchEntries.Select(e=>new JObject( new JProperty("location", e.Location), new JProperty("breadcrumbs", e.BreadCrumbs), new JProperty("keywords", e.Keywords), new JProperty("title", e.Title))) ) )); File.WriteAllText(Utils.MakeAbsolutePath(this.Destination, "search_index.json"), searchIndex.ToString()); } private void GenerateSearchPage(NavigationContext navigationContext) { var activePath = new NavigatedPath(); activePath.Push(this.Pages); var searchSimpleElement = new SimpleNavigationElement() {Name = "Search", Value = "Docnet_search.htm", IsIndexElement = false, ParentContainer = this.Pages}; searchSimpleElement.ContentProducerFunc = (e,c,n) =>@" <h1 id=""search"">Search Results</h1> <p> <form id=""content_search"" action=""Docnet_search.htm""> <span role= ""status"" aria-live=""polite"" class=""ui-helper-hidden-accessible""></span> <input name=""q"" id=""search-query"" type=""text"" class=""search_input search-query ui-autocomplete-input"" placeholder=""Search the Docs"" autocomplete=""off"" autofocus/> </form> </p> <div id=""search-results""> <p>Sorry, page not found.</p> </div>"; searchSimpleElement.ExtraScriptProducerFunc = (e,c,n) => @" <script>var base_url = '.';</script> <script data-main=""js/search.js"" src=""js/require.js""></script>"; // Force custom navigation context because this should end up in the root searchSimpleElement.GenerateOutput(this, activePath, new NavigationContext(PathSpecification.Full, UrlFormatting.None, 0, false)); activePath.Pop(); } #region Properties public string Name { get { return _configData.Name ?? string.Empty; } } public string Source { get { if(string.IsNullOrWhiteSpace(_docsSourcePath)) { _docsSourcePath = Utils.MakeAbsolutePath(_configFileSourcePath, (string)_configData.Source) ?? "."; } return _docsSourcePath; } } public string Destination { get { if(string.IsNullOrWhiteSpace(_destinationPath)) { _destinationPath = Utils.MakeAbsolutePath(_configFileSourcePath, (string)_configData.Destination) ?? "."; } return _destinationPath; } } public string StartingPageName { get { string rawName = _configData.StartingPageName; return string.IsNullOrWhiteSpace(rawName) ? "Home" : rawName; } } public string IncludeFolder { get { string rawIncludeFolder = _configData.IncludeSource; return string.IsNullOrWhiteSpace(rawIncludeFolder) ? "Includes" : rawIncludeFolder; } } public bool ConvertLocalLinks { get { return _configData.ConvertLocalLinks ?? false; } } public int MaxLevelInToC { get { return _configData.MaxLevelInToC ?? 2; } } public bool StripIndexHtm { get { return _configData.StripIndexHtm ?? false; } } public string ThemeName { get { string rawThemeName = _configData.Theme; return string.IsNullOrWhiteSpace(rawThemeName) ? "Default" : rawThemeName; } } public string ThemeFolder { get { if(string.IsNullOrWhiteSpace(_themeFolder)) { string rawThemeFolder = _configData.ThemeFolder; if(string.IsNullOrWhiteSpace(rawThemeFolder)) { // not specified, assume local theme folder. var exeRawFolderUri = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); if(exeRawFolderUri == null) { return string.Empty; // will end up as an error as themes now aren't found. } var exeFolder = new Uri(exeRawFolderUri).LocalPath; rawThemeFolder = Path.Combine(exeFolder, "Themes"); } else { rawThemeFolder = Utils.MakeAbsolutePath(_configFileSourcePath, (string)_configData.ThemeFolder) ?? "."; } _themeFolder = Path.Combine(rawThemeFolder, this.ThemeName); } return _themeFolder; } } public string PageTemplateFile { get { return Path.Combine(this.ThemeFolder, "PageTemplate.htm"); } } public string PageTemplateContents { get { return _templateContents ?? string.Empty; } } public PathSpecification PathSpecification { get { var pathSpecification = PathSpecification.Full; var pathSpecificationAsString = (string)_configData.PathSpecification; if (!string.IsNullOrWhiteSpace(pathSpecificationAsString)) { if (!Enum.TryParse(pathSpecificationAsString, true, out pathSpecification)) { pathSpecification = PathSpecification.Full; } } return pathSpecification; } } public UrlFormatting UrlFormatting { get { var urlFormatting = UrlFormatting.None; var urlFormattingAsString = (string)_configData.UrlFormatting; if (!string.IsNullOrWhiteSpace(urlFormattingAsString)) { if (!Enum.TryParse(urlFormattingAsString, true, out urlFormatting)) { urlFormatting = UrlFormatting.None; } } return urlFormatting; } } public NavigationLevel Pages { get { if(_pages == null) { JObject rawPages = _configData.Pages; _pages = new NavigationLevel(Source) {Name = StartingPageName, IsRoot = true}; _pages.Load(rawPages); } return _pages; } } public string Footer { get { return _configData.Footer ?? string.Empty; } } public List<string> SourceFoldersToCopy { get { JArray rawFolderNames = _configData.SourceFoldersToCopy; if(rawFolderNames == null) { return new List<string>(); } return rawFolderNames.HasValues ? rawFolderNames.Values<string>().ToList() : new List<string>(); } } #endregion } }