Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/docmaker-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ jobs:
Xvfb :99 &
echo "DISPLAY=:99" >> $GITHUB_ENV

- name: Install cmark-gfm on Linux
if: ${{ matrix.platform == 'ubuntu-latest' }}
run: sudo apt-get update && sudo apt-get install -y cmark-gfm

- name: Set up MATLAB on the runner
uses: matlab-actions/setup-matlab@v3
with:
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ Finally, configure [Markdown conversion](./tbx/docmakerdoc/conversion.md) by gen

DocMaker is developed by [David Sampson](https://www.mathworks.com/matlabcentral/profile/authors/16247) from [MathWorks](https://www.mathworks.com/services/consulting.html) on [GitHub](https://github.com/mathworks/docmaker).

DocMaker uses the [GitHub Markdown API](https://docs.github.com/en/rest/markdown) or the [GitLab Markdown API](https://docs.gitlab.com/api/markdown/) for converting Markdown to HTML, and the [GitHub Markdown CSS](https://github.com/sindresorhus/github-markdown-css) by [Sindre Sorhus](https://github.com/sindresorhus) for HTML styling.
DocMaker uses the [GitHub Markdown API](https://docs.github.com/en/rest/markdown),
the [GitLab Markdown API](https://docs.gitlab.com/api/markdown/), or local
[cmark-gfm](https://github.com/github/cmark-gfm) for converting Markdown to
HTML. It uses the [GitHub Markdown CSS](https://github.com/sindresorhus/github-markdown-css)
by [Sindre Sorhus](https://github.com/sindresorhus) for HTML styling.

The author thanks [Ken Deeley](https://www.mathworks.com/matlabcentral/profile/authors/2987674) from MathWorks for his support during the development of DocMaker.

Expand Down
5 changes: 5 additions & 0 deletions buildfile.m
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ function packageTask( ~ )
s.ToolboxName = v.Name;
s.ToolboxVersion = v.Version;

% Specify the package name from R2026b
if ~isMATLABReleaseOlderThan( "R2026b" )
s.PackageName = s.Name;
end % if

if getenv( "GITHUB_ACTIONS" ) == "true"
% Check version and tag compatibility for release
ref = string( getenv( "GITHUB_REF" ) );
Expand Down
1 change: 1 addition & 0 deletions docmaker.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"Name":"MATLAB_DocMaker",
"Identifier":"ae82d5d2-45be-4fc5-a01b-70d8bb905ca2",
"Summary":"Create MATLAB toolbox documentation from Markdown documents and MATLAB scripts",
"Description":"With DocMaker, you can:\n* write documentation in Markdown and convert to HTML for viewing in MATLAB\n* run MATLAB scripts and capture output as images for inclusion in documentation\n* create MATLAB documentation index files from a Markdown table of contents",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info>
<Category UUID="FileClassCategory">
<Label UUID="design"/>
</Category>
</Info>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="LocalCmark.m" type="File"/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="1" type="DIR_SIGNIFIER"/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info>
<Category UUID="FileClassCategory">
<Label UUID="test"/>
</Category>
</Info>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="tLocalCmark.m" type="File"/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info>
<Category UUID="FileClassCategory">
<Label UUID="test"/>
</Category>
</Info>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="tconverter.m" type="File"/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="+docmaker" type="File"/>
4 changes: 2 additions & 2 deletions tbx/docmaker/+docmaker/GitHub.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
end

obj.Hostname = hostname;
obj.Token_ = token;
obj.Token_ = docmaker.MarkdownConverter.normalizeToken( token );

end % constructor

Expand Down Expand Up @@ -95,4 +95,4 @@

end % methods

end % classdef
end % classdef
2 changes: 1 addition & 1 deletion tbx/docmaker/+docmaker/GitLab.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
end

obj.Hostname = hostname;
obj.Token_ = token;
obj.Token_ = docmaker.MarkdownConverter.normalizeToken( token );

end % constructor

Expand Down
100 changes: 100 additions & 0 deletions tbx/docmaker/+docmaker/LocalCmark.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
classdef LocalCmark < docmaker.MarkdownConverter
%docmaker.LocalCmark Local cmark-gfm Markdown converter
%
% docmaker.LocalCmark uses the local cmark-gfm binary to convert
% Markdown to HTML without making network calls.
%
% c = docmaker.LocalCmark() creates a converter using cmark-gfm on
% the system path.
%
% c = docmaker.LocalCmark(b) uses the binary at path b.

% Copyright 2026 The MathWorks, Inc.

properties ( SetAccess = immutable )
Binary(1, 1) string
end % properties ( SetAccess = immutable )

methods

function obj = LocalCmark( binary )
%LocalCmark Local cmark-gfm Markdown converter

arguments ( Input )
binary(1, 1) string = "cmark-gfm"
end % arguments ( Input )

validateBinary( binary )
obj.Binary = binary;

end % constructor

function doc = md2xml( obj, md )
%md2xml Convert Markdown to XML
%
% x = md2xml(c,md) converts the Markdown md to the XML
% document x using the local cmark-gfm binary.

arguments ( Input )
obj(1, 1) docmaker.LocalCmark
md(1, 1) string
end % arguments ( Input )

% Write Markdown content to a temporary file.
tmpIn = tempname() + ".md";
cleaner = onCleanup( @() cleanupTempFile( tmpIn ) );
writelines( md, tmpIn, "Encoding", "UTF-8" );

% Invoke the binary on the temporary file.
command = sprintf( [ ...
'"%s" --extension table --extension strikethrough ' ...
'--extension autolink --extension tasklist ' ...
'--extension tagfilter --to html "%s" 2>&1' ], ...
obj.Binary, tmpIn );
[status, output] = system( command );
xml = strip( string( output ) );

if status ~= 0
if xml == ""
xml = "No diagnostic output was returned.";
end
error( "docmaker:LocalCmark:ProcessFailed", ...
"Unable to run cmark-gfm binary ""%s"" " + ...
"(status %d): %s", ...
obj.Binary, status, xml )
end % if

% Close tags and parse.
xml = docmaker.closetags( xml, "img" );
xml = docmaker.closetags( xml, "hr" );
xml = docmaker.closetags( xml, "br" );
parser = matlab.io.xml.dom.Parser();
doc = parser.parseString( "<div>" + xml + "</div>" );
doc.XMLStandalone = true;

end % md2xml

end % methods

end % classdef

function validateBinary( binary )
%validateBinary Reject binary values unsafe for shell invocation.

unsafeCharacters = ["""", "$", "`", "&", "|", "<", ">", "^", ...
"%", "!", ";", newline, string( char( 13 ) )];
if any( contains( binary, unsafeCharacters ) )
error( "docmaker:LocalCmark:InvalidBinary", ...
"Binary must not contain shell metacharacters." )
end % if

end % validateBinary

function cleanupTempFile( filePath )
%cleanupTempFile Delete a temporary file when it exists.

if isfile( filePath )
delete( filePath )
end % if

end % cleanupTempFile
19 changes: 18 additions & 1 deletion tbx/docmaker/+docmaker/MarkdownConverter.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,21 @@
xml = md2xml( md )
end

end % classdef
methods ( Static, Access = protected )

function token = normalizeToken( token )
%normalizeToken Normalize an access token

arguments
token(1, 1) string
end

if ~ismissing( token ) && strlength( token ) == 0
token = missing;
end

end % normalizeToken

end % methods ( Access = protected )

end % classdef
19 changes: 12 additions & 7 deletions tbx/docmaker/+docmaker/converter.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,32 @@
%
% c = docmaker.converter() returns the current Markdown converter.
%
% The converter can be "GitHub" (default) or "GitLab" and is controlled
% by the environment variable DOCMAKER_CONVERTER, the secret "DocMaker
% converter" or the preference "converter".
% The converter can be "GitHub" (default), "GitLab", or "LocalCmark" and
% is controlled by the environment variable DOCMAKER_CONVERTER, the
% secret "DocMaker converter" or the preference "converter".
%
% The GitHub hostname and token are stored in DOCMAKER_GITHUB_HOSTNAME
% and DOCMAKER_GITHUB_TOKEN, "DocMaker GitHub hostname" and "DocMaker
% GitHub token", or "github_hostname" and "github_token". The same naming
% convention applies to GitLab.
% convention applies to GitLab. The LocalCmark binary is configured by
% DOCMAKER_LOCALCMARK_BINARY, "DocMaker LocalCmark binary", or
% "localcmark_binary".

% Copyright 2024-2026 The MathWorks, Inc.

n = getValue( "converter", "GitHub" );
switch lower( n )
case "github"
h = getValue( "GitHub hostname", "api.github.com" );
t = getValue( "GitHub token", "" );
t = getValue( "GitHub token", missing );
c = docmaker.GitHub( h, t );
case "gitlab"
h = getValue( "GitLab hostname", "www.gitlab.com" );
t = getValue( "GitLab token", "" );
t = getValue( "GitLab token", missing );
c = docmaker.GitLab( h, t );
case "localcmark"
b = getValue( "LocalCmark binary", "cmark-gfm" );
c = docmaker.LocalCmark( b );
otherwise
error( "docmaker:Unhandled", "Unknown converter ""%s"".", n )
end
Expand Down Expand Up @@ -74,4 +79,4 @@
tf = HAS_SECRETS; % retrieve
end

end % hasSecrets
end % hasSecrets
11 changes: 6 additions & 5 deletions tbx/docmaker/Contents.m
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
% MATLAB DocMaker
% Version 0.8.0 (R2026b) 15-Oct-2026
% Version 0.8.1 (R2026b) 29-Oct-2026
%
% docconvert - convert Markdown documents to HTML
% docrun - run MATLAB code in HTML documents and insert output
% docindex - create documentation index files
% docdelete - delete generated artifacts
% docconvert - convert Markdown documents to HTML
% docrun - run MATLAB code in HTML documents and insert output
% docindex - create documentation index files
% docdelete - delete generated artifacts
% DocMakerTask - generate documentation in a build file

% Copyright 2020-2026 The MathWorks, Inc.
14 changes: 8 additions & 6 deletions tbx/docmaker/docconvert.m
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,12 @@
end % relpath

function cleanLaTeXExpressions( fHTML )
%CLEANLATEXEXPRESSIONS Postprocess LaTeX expressions after conversion to
%HTML via the GitHub or GitLab APIs. We remove spurious HTML tags and add
%delimiters to the expressions as needed.
%CLEANLATEXEXPRESSIONS Postprocess LaTeX expressions after Markdown
%conversion. We remove spurious HTML tags and add delimiters to the
%expressions as needed.
%
% For the GitHub API, we replace <em>...</em> with _..._ inside $...$ or
% $$...$$.
% For GitHub and LocalCmark, we replace <em>...</em> with _..._ inside
% $...$ or $$...$$.
%
% Markdown italics and LaTeX subscripts both use an underscore, causing a
% conflict when Markdown is parsed with priority over LaTeX inside a LaTeX
Expand Down Expand Up @@ -321,6 +321,8 @@ function cleanLaTeXExpressions( fHTML )
switch converterType
case "GitHub"
removeItalicTags( fHTML )
case "LocalCmark"
removeItalicTags( fHTML )
case "GitLab"
wrapMathSpans( fHTML )
otherwise
Expand Down Expand Up @@ -410,4 +412,4 @@ function wrapMathSpans( fHTML )
fprintf( fileID, "%s", cleanHTML );
fclose( fileID );

end % wrapMathSpans
end % wrapMathSpans
8 changes: 6 additions & 2 deletions tbx/docmakerdoc/about.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

DocMaker is developed by [David Sampson](https://www.mathworks.com/matlabcentral/profile/authors/16247) from [MathWorks](https://www.mathworks.com/services/consulting.html) on [GitHub](https://github.com/mathworks/docmaker).

DocMaker uses the [GitHub Markdown API](https://docs.github.com/en/rest/markdown) or the [GitLab Markdown API](https://docs.gitlab.com/api/markdown/) for converting Markdown to HTML, and the [GitHub Markdown CSS](https://github.com/sindresorhus/github-markdown-css) by [Sindre Sorhus](https://github.com/sindresorhus) for HTML styling.
DocMaker uses the [GitHub Markdown API](https://docs.github.com/en/rest/markdown),
the [GitLab Markdown API](https://docs.gitlab.com/api/markdown/), or local
[cmark-gfm](https://github.com/github/cmark-gfm) for converting Markdown to
HTML. It uses the [GitHub Markdown CSS](https://github.com/sindresorhus/github-markdown-css)
by [Sindre Sorhus](https://github.com/sindresorhus) for HTML styling.

The author thanks [Ken Deeley](https://www.mathworks.com/matlabcentral/profile/authors/2987674) from MathWorks for his support during the development of DocMaker.

Expand All @@ -18,4 +22,4 @@ DocMaker was developed to build documentation for [GUI Layout Toolbox](http://ww

___

[home](index.md) :house: | :copyright: [MathWorks](https://www.mathworks.com/services/consulting.html) 2024-2026
[home](index.md) :house: | :copyright: [MathWorks](https://www.mathworks.com/services/consulting.html) 2024-2026
7 changes: 6 additions & 1 deletion tbx/docmakerdoc/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Release notes

## Version 0.8.1

* Added optional offline Markdown conversion with local [cmark-gfm](https://github.com/github/cmark-gfm)
* Fixed empty GitHub and GitLab access token settings to send unauthenticated requests

## Version 0.8.0

* Added support for LaTeX expressions using [MathJax](https://www.mathjax.org/) via the `Interpreter="latex"` option in `docconvert`
Expand All @@ -23,4 +28,4 @@

___

:copyright: [MathWorks](https://www.mathworks.com/services/consulting.html) 2024-2026
:copyright: [MathWorks](https://www.mathworks.com/services/consulting.html) 2024-2026
Loading
Loading