Guest User

Untitled

a guest
Jan 26th, 2025
24
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
MatLab 9.73 KB | Source Code | 0 0
  1. function HtmlOutput = convertMarkdownToHtml2(InputFile, options)
  2.     % CONVERTMARKDOWNTOHTML Convert a Markdown file to HTML
  3.     %   HtmlOutput = convertMarkdownToHtml(InputFile) converts the markdown file
  4.     %   to HTML and saves it with the same name but .html extension
  5.     %  
  6.     %   HtmlOutput = convertMarkdownToHtml(InputFile, 'OutputFile', filename)
  7.     %   saves the HTML to the specified filename
  8.     %  
  9.     %   HtmlOutput = convertMarkdownToHtml(..., 'DoBase64Encoding', true)
  10.     %   encodes images as base64 within the HTML file
  11.     %
  12.     %   HtmlOutput = convertMarkdownToHtml(..., 'DoSyntaxHighlight', true)
  13.     %   adds syntax highlighting for code blocks using Prism.js
  14.    
  15.     arguments
  16.         InputFile (1,1) string {mustBeFile}
  17.         options.OutputFile (1,1) string = replace(InputFile, '.md', '.html')
  18.         options.DoBase64Encoding (1,1) logical = false
  19.         options.DoSyntaxHighlight (1,1) logical = false
  20.     end
  21.    
  22.     % Read the markdown file
  23.     FileContent = string(fileread(InputFile));
  24.     Lines = splitlines(FileContent);
  25.    
  26.     % Initialize HTML content
  27.     HtmlContent = strings(0);
  28.     HtmlContent = [HtmlContent; "<!DOCTYPE html>"; "<html>"; "<head>"; ...
  29.         "<meta charset=""utf-8"">"];
  30.    
  31.     % Add Prism.js resources if syntax highlighting is enabled
  32.     if options.DoSyntaxHighlight
  33.         HtmlContent = [HtmlContent;
  34.             "<link href=""https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css"" rel=""stylesheet"" />";
  35.             "<link href=""https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/line-numbers/prism-line-numbers.min.css"" rel=""stylesheet"" />";
  36.             ];
  37.     end
  38.    
  39.     HtmlContent = [HtmlContent; "</head>"];
  40.     if options.DoSyntaxHighlight
  41.         HtmlContent = [HtmlContent; "<body class=""line-numbers"">"];
  42.     else
  43.         HtmlContent = [HtmlContent; "<body>"];
  44.     end
  45.    
  46.     % Process the content
  47.     IsInCodeBlock = false;
  48.     IsInList = false;
  49.     CurrentCodeLanguage = "";
  50.    
  51.     for i = 1:length(Lines)
  52.         CurrentLine = Lines(i);
  53.        
  54.         % Handle code blocks
  55.         if startsWith(strip(CurrentLine), "```")
  56.             if ~IsInCodeBlock
  57.                 % Starting a code block
  58.                 Language = extractAfter(strip(CurrentLine), "```");
  59.                 CurrentCodeLanguage = determineLanguage(Language);
  60.                 if options.DoSyntaxHighlight
  61.                     HtmlContent = [HtmlContent; ...
  62.                         sprintf("<pre class=""line-numbers""><code class=""language-%s"">", ...
  63.                         CurrentCodeLanguage)];
  64.                 else
  65.                     HtmlContent = [HtmlContent; "<pre><code>"];
  66.                 end
  67.                 IsInCodeBlock = true;
  68.             else
  69.                 % Ending a code block
  70.                 HtmlContent = [HtmlContent; "</code></pre>"];
  71.                 IsInCodeBlock = false;
  72.                 CurrentCodeLanguage = "";
  73.             end
  74.             continue;
  75.         end
  76.        
  77.         if IsInCodeBlock
  78.             HtmlContent = [HtmlContent; htmlEncode(CurrentLine)];
  79.             continue;
  80.         end
  81.        
  82.         % Handle headers
  83.         if startsWith(strip(CurrentLine), "#")
  84.             [HeadingLevel, HeadingText] = parseHeading(CurrentLine);
  85.             HtmlContent = [HtmlContent; ...
  86.                 sprintf("<h%d>%s</h%d>", HeadingLevel, HeadingText, HeadingLevel)];
  87.             continue;
  88.         end
  89.        
  90.         % Handle task lists and regular lists
  91.         if startsWith(strip(CurrentLine), "- ")
  92.             if ~IsInList
  93.                 HtmlContent = [HtmlContent; "<ul>"];
  94.                 IsInList = true;
  95.             end
  96.            
  97.             % Check for task list item
  98.             if contains(CurrentLine, "- [ ]") || contains(CurrentLine, "- [x]")
  99.                 IsChecked = contains(CurrentLine, "- [x]");
  100.                 TaskText = extractAfter(CurrentLine, "]");
  101.                 CheckboxHtml = sprintf('<input type="checkbox" %s disabled> %s', ...
  102.                     conditionalString(IsChecked, "checked", ""), ...
  103.                     strip(TaskText));
  104.                 HtmlContent = [HtmlContent; "<li>" + CheckboxHtml + "</li>"];
  105.             else
  106.                 ListItem = extractAfter(CurrentLine, "- ");
  107.                 HtmlContent = [HtmlContent; "<li>" + processInlineMarkdown(ListItem) + "</li>"];
  108.             end
  109.             continue;
  110.         elseif IsInList && ~isempty(strip(CurrentLine))
  111.             HtmlContent = [HtmlContent; "</ul>"];
  112.             IsInList = false;
  113.         end
  114.        
  115.         % Handle images
  116.         if contains(CurrentLine, "![")
  117.             HtmlContent = [HtmlContent; processImages(CurrentLine, ...
  118.                 fileparts(InputFile), options.DoBase64Encoding)];
  119.             continue;
  120.         end
  121.        
  122.         % Handle regular paragraphs
  123.         if ~isempty(strip(CurrentLine))
  124.             HtmlContent = [HtmlContent; "<p>" + processInlineMarkdown(CurrentLine) + "</p>"];
  125.         end
  126.     end
  127.    
  128.     % Close any open lists
  129.     if IsInList
  130.         HtmlContent = [HtmlContent; "</ul>"];
  131.     end
  132.    
  133.     % Add Prism.js scripts if syntax highlighting is enabled
  134.     if options.DoSyntaxHighlight
  135.         HtmlContent = [HtmlContent;
  136.             "<script src=""https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js""></script>";
  137.             "<script src=""https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js""></script>";
  138.             "<script src=""https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/line-numbers/prism-line-numbers.min.js""></script>";
  139.             "<script src=""https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-matlab.min.js""></script>";
  140.             ];
  141.     end
  142.    
  143.     % Close HTML document
  144.     HtmlContent = [HtmlContent; "</body>"; "</html>"];
  145.    
  146.     % Write the output file
  147.     HtmlOutput = options.OutputFile;
  148.     writelines(HtmlContent, HtmlOutput);
  149. end
  150.  
  151. function [Level, Text] = parseHeading(Line)
  152.     % Parse markdown heading to get level and text
  153.     LineChar = Line{1};
  154.     Level = sum(LineChar == '#');
  155.     Text = strip(extractAfter(Line, repmat('#', 1, Level)));
  156. end
  157.  
  158. function Output = processInlineMarkdown(Line)
  159.     % Process inline markdown syntax
  160.    
  161.     % Bold
  162.     Line = regexprep(Line, '\*\*([^\*]+)\*\*', '<strong>$1</strong>');
  163.    
  164.     % Italic
  165.     Line = regexprep(Line, '\*([^\*]+)\*', '<em>$1</em>');
  166.    
  167.     % Code
  168.     Line = regexprep(Line, '`([^`]+)`', '<code>$1</code>');
  169.    
  170.     % Links
  171.     Line = regexprep(Line, '\[([^\]]+)\]\(([^\)]+)\)', '<a href="$2">$1</a>');
  172.    
  173.     Output = Line;
  174. end
  175.  
  176. function EncodedStr = htmlEncode(Str)
  177.     % Encode special HTML characters
  178.     EncodedStr = replace(Str, "&", "&amp;");
  179.     EncodedStr = replace(EncodedStr, "<", "&lt;");
  180.     EncodedStr = replace(EncodedStr, ">", "&gt;");
  181.     EncodedStr = replace(EncodedStr, """", "&quot;");
  182. end
  183.  
  184. function Output = processImages(Line, BasePath, DoBase64)
  185.     % Process markdown image syntax
  186.     [AltText, ImagePath] = extractImageInfo(Line);
  187.    
  188.     if ~startsWith(ImagePath, ["http://", "https://", "/"])
  189.         % Relative path - make it absolute
  190.         ImagePath = fullfile(BasePath, ImagePath);
  191.     end
  192.    
  193.     if DoBase64 && ~startsWith(ImagePath, ["http://", "https://"])
  194.         try
  195.             [~, ~, Ext] = fileparts(ImagePath);
  196.             % Correctly read binary file data
  197.             Fid = fopen(ImagePath, 'rb');
  198.             if Fid == -1
  199.                 error('Could not open image file');
  200.             end
  201.             ImageData = fread(Fid, Inf, '*uint8');
  202.             fclose(Fid);
  203.            
  204.             % Convert to base64
  205.             Base64Data = matlab.net.base64encode(ImageData);
  206.            
  207.             % Get correct MIME type
  208.             MimeType = getMimeType(Ext);
  209.             ImgSrc = sprintf('data:%s;base64,%s', MimeType, char(Base64Data));
  210.         catch ME
  211.             warning('Could not encode image %s: %s', ImagePath, ME.message);
  212.             ImgSrc = ImagePath;
  213.         end
  214.     else
  215.         ImgSrc = ImagePath;
  216.     end
  217.    
  218.     Output = sprintf('<img src="%s" alt="%s">', ImgSrc, AltText);
  219. end
  220.  
  221. function [AltText, ImagePath] = extractImageInfo(Line)
  222.     % Extract alt text and image path from markdown image syntax
  223.     LineChar = Line{1};
  224.     AltStart = find(LineChar == '[', 1) + 1;
  225.     AltEnd = find(LineChar == ']', 1) - 1;
  226.     PathStart = find(LineChar == '(', 1) + 1;
  227.     PathEnd = find(LineChar == ')', 1) - 1;
  228.    
  229.     AltText = string(LineChar(AltStart:AltEnd));
  230.     ImagePath = string(LineChar(PathStart:PathEnd));
  231. end
  232.  
  233. function MimeType = getMimeType(Ext)
  234.     % Return appropriate MIME type for the image extension
  235.     switch lower(Ext)
  236.         case '.jpg'
  237.             MimeType = 'image/jpeg';
  238.         case '.jpeg'
  239.             MimeType = 'image/jpeg';
  240.         case '.png'
  241.             MimeType = 'image/png';
  242.         case '.gif'
  243.             MimeType = 'image/gif';
  244.         case '.webp'
  245.             MimeType = 'image/webp';
  246.         case '.svg'
  247.             MimeType = 'image/svg+xml';
  248.         otherwise
  249.             MimeType = 'image/png'; % default fallback
  250.     end
  251. end
  252.  
  253. function Language = determineLanguage(Lang)
  254.     % Determine the language class for Prism.js
  255.     % Focus on MATLAB, fallback to plain text for others
  256.     Lang = lower(strip(Lang));
  257.    
  258.     if isempty(Lang)
  259.         Language = "plain";
  260.     elseif ismember(Lang, ["matlab", "m"])
  261.         Language = "matlab";
  262.     else
  263.         Language = "plain";
  264.     end
  265. end
  266.  
  267. function Str = conditionalString(Condition, TrueStr, FalseStr)
  268.     % Return string based on condition
  269.     if Condition
  270.         Str = TrueStr;
  271.     else
  272.         Str = FalseStr;
  273.     end
  274. end
Add Comment
Please, Sign In to add comment