示例#1
0
        /// <summary>
        /// Not doing duplication check here, do it outside
        /// </summary>
        /// <param name="markdownFilePath"></param>
        /// <param name="resolvedContent"></param>
        /// <param name="referenceFolder"></param>
        /// <param name="yamlHandler"></param>
        /// <param name="markdown"></param>
        /// <returns></returns>
        public static ParseResult TryParseCustomizedMarkdown(string markdownFilePath, string resolvedContent, string referenceFolder, Func <MetadataItem, ParseResult> yamlHandler, out List <MarkdownIndex> markdown)
        {
            var gitDetail = GitUtility.GetGitDetail(markdownFilePath);

            if (string.IsNullOrEmpty(resolvedContent))
            {
                resolvedContent = File.ReadAllText(markdownFilePath);
            }
            string          markdownFile = resolvedContent;
            int             length       = markdownFile.Length;
            var             yamlRegex    = new Regex(@"\-\-\-((?!\n)\s)*\n((?!\n)\s)*(?<content>.*)((?!\n)\s)*\n\-\-\-((?!\n)\s)*\n", RegexOptions.Compiled | RegexOptions.Multiline);
            MatchCollection matches      = yamlRegex.Matches(markdownFile);

            if (matches.Count == 0)
            {
                markdown = new List <MarkdownIndex>();
                return(new ParseResult(ResultLevel.Warn, "no valid yaml header is found in {0}", markdownFilePath));
            }

            int                  startIndex  = 0;
            MarkdownIndex        lastSection = null;
            List <MarkdownIndex> sections    = new List <MarkdownIndex>();

            StringBuilder error = new StringBuilder();

            for (int i = 0; i < matches.Count; i++)
            {
                var    match   = matches[i];
                string content = match.Groups["content"].Value;

                MetadataItem viewModel;
                // Content to yaml
                try
                {
                    using (StringReader reader = new StringReader(content))
                    {
                        viewModel = YamlUtility.Deserialize <MetadataItem>(reader);

                        if (string.IsNullOrEmpty(viewModel.Name))
                        {
                            throw new ArgumentException("Name for yaml header is required");
                        }

                        // TODO: override metadata, merge viewmodel?

                        if (yamlHandler != null)
                        {
                            ParseResult result = yamlHandler(viewModel);
                            if (result.ResultLevel != ResultLevel.Success)
                            {
                                throw new ArgumentException(result.Message);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    error.AppendFormat("{0} in {1} line {2} is not in a valid yaml format {3}", match.Value, markdownFilePath, markdownFile.Substring(0, startIndex).Split('\n').Length + 2, e.Message);
                    continue;
                }

                startIndex = match.Index + match.Length;
                if (lastSection != null)
                {
                    lastSection.ContentEndIndex = match.Index - 1;

                    if (lastSection.ContentEndIndex > lastSection.ContentStartIndex)
                    {
                        lastSection.MarkdownContent = markdownFile.Substring(lastSection.ContentStartIndex, lastSection.ContentEndIndex - lastSection.ContentStartIndex + 1);
                        lastSection.Path            = lastSection.Path.FormatPath(UriKind.Relative, lastSection.Remote.LocalWorkingDirectory);
                        ExtractReferenceFromMdSection(ref lastSection, referenceFolder);
                        sections.Add(lastSection);
                    }
                }

                lastSection = new MarkdownIndex {
                    ApiName = viewModel.Name, ContentStartIndex = startIndex, ContentEndIndex = length - 1, Remote = gitDetail, Path = markdownFilePath
                };                                                                                                                                                                       // endIndex should be set from next match if there is next match
                if (lastSection.ContentEndIndex > lastSection.ContentStartIndex)
                {
                    lastSection.MarkdownContent = markdownFile.Substring(lastSection.ContentStartIndex);
                }
            }

            if (lastSection != null)
            {
                if (lastSection.Remote != null && !string.IsNullOrEmpty(lastSection.Remote.LocalWorkingDirectory))
                {
                    lastSection.Path = lastSection.Path.FormatPath(UriKind.Relative, lastSection.Remote.LocalWorkingDirectory);
                }
                ExtractReferenceFromMdSection(ref lastSection, referenceFolder);
                sections.Add(lastSection);
            }

            markdown = sections;
            if (error.Length > 0)
            {
                return(new ParseResult(ResultLevel.Warn, error.ToString()));
            }

            return(new ParseResult(ResultLevel.Success));
        }
示例#2
0
        /// <summary>
        /// Extrac code snippet from markdown files.
        /// Code snippet syntax: {{"relativePath/sourceFilename"}} or {{"relativePath/sourceFilename"[startline-endline]}}
        /// where starline and endline should be integers and are both optional,
        /// the default values for which are 1 and the fileLength.
        /// </summary>
        /// <param name="section"></param>
        /// <param name="referenceFolder"></param>
        private static void ExtractReferenceFromMdSection(ref MarkdownIndex section, string referenceFolder)
        {
            var             ReferenceRegex = new Regex(@"{{\s*""(?<source>\S*?)""\s*(\[(?<line>\d*-\d*?)\])?\s*}}", RegexOptions.Multiline);
            MatchCollection matches        = ReferenceRegex.Matches(section.MarkdownContent);

            if (matches.Count > 0)
            {
                if (Directory.Exists(referenceFolder))
                {
                    ParseResult.WriteToConsole(ResultLevel.Warn, "Folder {0} already exists!", referenceFolder);
                }
                else
                {
                    Directory.CreateDirectory(referenceFolder);
                }

                for (int i = 0; i < matches.Count; i++)
                {
                    var    match  = matches[i];
                    string source = match.Groups["source"].Value.Trim();
                    string line   = match.Groups["line"].Value.Trim();

                    MarkdownIndex item = new MarkdownIndex();
                    item.ApiName = source;
                    string sourceFile = Path.Combine(Path.GetDirectoryName(section.Path), source.Replace('/', '\\'));
                    item.Path = sourceFile;
                    string destFile = Path.Combine(referenceFolder, sourceFile.ToValidFilePath());
                    sourceFile = Path.Combine(section.Remote.LocalWorkingDirectory, sourceFile);

                    if (!ReferencedFileLengthCache.ContainsKey(destFile))
                    {
                        try
                        {
                            File.Copy(sourceFile, destFile, true);
                        }
                        catch (Exception e)
                        {
                            ParseResult.WriteToConsole(ResultLevel.Error, "Unable to copy referenced file {0} to output directory {1}: {2}", sourceFile, referenceFolder, e.Message);
                            continue;
                        }
                    }

                    item.ContentStartIndex = section.ContentStartIndex + match.Index;
                    item.ContentEndIndex   = item.ContentStartIndex + match.Length - 1;

                    if (!string.IsNullOrEmpty(line))
                    {
                        try
                        {
                            string[] lines = line.Split('-');
                            int      startline = 0, endLine = 0;

                            if (string.IsNullOrEmpty(lines[0]))
                            {
                                startline = 1;
                            }
                            else
                            {
                                startline = Convert.ToInt32(lines[0]);
                            }

                            int fileLength;
                            if (!ReferencedFileLengthCache.TryGetValue(destFile, out fileLength))
                            {
                                fileLength = File.ReadLines(destFile).Count();
                                ReferencedFileLengthCache.Add(destFile, fileLength);
                            }

                            if (string.IsNullOrEmpty(lines[1]))
                            {
                                endLine = fileLength;
                            }
                            else
                            {
                                endLine = Convert.ToInt32(lines[1]);
                            }

                            if (endLine < startline || startline < 1 || endLine > fileLength)
                            {
                                throw new Exception(string.Format("Span infromation about referenced file {0} form line {1} to {2} is invalid", sourceFile, startline.ToString(), endLine.ToString()));
                            }
                            else
                            {
                                item.ReferenceStartLine = startline;
                                item.ReferenceEndLine   = endLine;
                                item.ApiName           += string.Format("[{0}-{1}]", startline, endLine);
                            }
                        }
                        catch (Exception e)
                        {
                            ParseResult.WriteToConsole(ResultLevel.Error, "Cannot extract span infromation about referenced file {0}: {1}", sourceFile, e.Message);
                            continue;
                        }
                    }

                    if (section.Items == null)
                    {
                        section.Items = new List <MarkdownIndex>();
                    }
                    section.Items.Add(item);
                }
            }
        }