From 53e0873e9eced859912a47c99adb44346374fb14 Mon Sep 17 00:00:00 2001 From: Ken Deeley Date: Fri, 29 May 2026 10:44:37 +0100 Subject: [PATCH 1/3] Task infrastructure --- .../CptS6RPf-mdxP3OCPbhz6pVfFugd.xml | 6 ++ .../CptS6RPf-mdxP3OCPbhz6pVfFugp.xml | 2 + .../xSrPVEHhWJ_-24ZQrCFK7aG8Q6Ad.xml | 6 ++ .../xSrPVEHhWJ_-24ZQrCFK7aG8Q6Ap.xml | 2 + .../yuhCpIfVpbHV0GQ9EbmmIRF4rx8d.xml | 6 ++ .../yuhCpIfVpbHV0GQ9EbmmIRF4rx8p.xml | 2 + tbx/docmaker/+docmaker/getDefaultFigureSize.m | 7 ++ tbx/docmaker/+docmaker/mustBeTheme.m | 10 +++ tbx/docmaker/DocMakerTask.m | 87 +++++++++++++++++++ tbx/docmaker/docrun.m | 25 +----- 10 files changed, 131 insertions(+), 22 deletions(-) create mode 100644 resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/CptS6RPf-mdxP3OCPbhz6pVfFugd.xml create mode 100644 resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/CptS6RPf-mdxP3OCPbhz6pVfFugp.xml create mode 100644 resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/xSrPVEHhWJ_-24ZQrCFK7aG8Q6Ad.xml create mode 100644 resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/xSrPVEHhWJ_-24ZQrCFK7aG8Q6Ap.xml create mode 100644 resources/project/W7civUV8nZd65rl1QJN6xmVMVQI/yuhCpIfVpbHV0GQ9EbmmIRF4rx8d.xml create mode 100644 resources/project/W7civUV8nZd65rl1QJN6xmVMVQI/yuhCpIfVpbHV0GQ9EbmmIRF4rx8p.xml create mode 100644 tbx/docmaker/+docmaker/getDefaultFigureSize.m create mode 100644 tbx/docmaker/+docmaker/mustBeTheme.m create mode 100644 tbx/docmaker/DocMakerTask.m diff --git a/resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/CptS6RPf-mdxP3OCPbhz6pVfFugd.xml b/resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/CptS6RPf-mdxP3OCPbhz6pVfFugd.xml new file mode 100644 index 0000000..99772b4 --- /dev/null +++ b/resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/CptS6RPf-mdxP3OCPbhz6pVfFugd.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/CptS6RPf-mdxP3OCPbhz6pVfFugp.xml b/resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/CptS6RPf-mdxP3OCPbhz6pVfFugp.xml new file mode 100644 index 0000000..c9a70fe --- /dev/null +++ b/resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/CptS6RPf-mdxP3OCPbhz6pVfFugp.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/xSrPVEHhWJ_-24ZQrCFK7aG8Q6Ad.xml b/resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/xSrPVEHhWJ_-24ZQrCFK7aG8Q6Ad.xml new file mode 100644 index 0000000..99772b4 --- /dev/null +++ b/resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/xSrPVEHhWJ_-24ZQrCFK7aG8Q6Ad.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/xSrPVEHhWJ_-24ZQrCFK7aG8Q6Ap.xml b/resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/xSrPVEHhWJ_-24ZQrCFK7aG8Q6Ap.xml new file mode 100644 index 0000000..8d95e0a --- /dev/null +++ b/resources/project/UMvhTnfaEKsbCRaOOLl1x86F4Is/xSrPVEHhWJ_-24ZQrCFK7aG8Q6Ap.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/resources/project/W7civUV8nZd65rl1QJN6xmVMVQI/yuhCpIfVpbHV0GQ9EbmmIRF4rx8d.xml b/resources/project/W7civUV8nZd65rl1QJN6xmVMVQI/yuhCpIfVpbHV0GQ9EbmmIRF4rx8d.xml new file mode 100644 index 0000000..99772b4 --- /dev/null +++ b/resources/project/W7civUV8nZd65rl1QJN6xmVMVQI/yuhCpIfVpbHV0GQ9EbmmIRF4rx8d.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/resources/project/W7civUV8nZd65rl1QJN6xmVMVQI/yuhCpIfVpbHV0GQ9EbmmIRF4rx8p.xml b/resources/project/W7civUV8nZd65rl1QJN6xmVMVQI/yuhCpIfVpbHV0GQ9EbmmIRF4rx8p.xml new file mode 100644 index 0000000..5dd7fdc --- /dev/null +++ b/resources/project/W7civUV8nZd65rl1QJN6xmVMVQI/yuhCpIfVpbHV0GQ9EbmmIRF4rx8p.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/tbx/docmaker/+docmaker/getDefaultFigureSize.m b/tbx/docmaker/+docmaker/getDefaultFigureSize.m new file mode 100644 index 0000000..91d4544 --- /dev/null +++ b/tbx/docmaker/+docmaker/getDefaultFigureSize.m @@ -0,0 +1,7 @@ +function s = getDefaultFigureSize() +%getDefaultFigureSize Default figure size + +p = get( 0, "DefaultFigurePosition" ); % [x y w h] +s = p(3:4); % [w h] + +end % getDefaultFigureSize \ No newline at end of file diff --git a/tbx/docmaker/+docmaker/mustBeTheme.m b/tbx/docmaker/+docmaker/mustBeTheme.m new file mode 100644 index 0000000..cc24c11 --- /dev/null +++ b/tbx/docmaker/+docmaker/mustBeTheme.m @@ -0,0 +1,10 @@ +function mustBeTheme( theme ) +%mustBeTheme Validation function for optional named argument Theme + +themes = ["none","light","dark","auto"]; +assert( ( ischar( theme ) && ismember( theme, themes ) ) || ... + ( isstring( theme ) && isscalar( theme ) && ismember( theme, themes ) ) || ... + ( isa( theme, "matlab.graphics.theme.GraphicsTheme" ) && isscalar( theme ) ), ... + "Theme must be ""none"", ""light"", ""dark"", ""auto"", or a GraphicsTheme." ) + +end % mustBeTheme \ No newline at end of file diff --git a/tbx/docmaker/DocMakerTask.m b/tbx/docmaker/DocMakerTask.m new file mode 100644 index 0000000..93c8726 --- /dev/null +++ b/tbx/docmaker/DocMakerTask.m @@ -0,0 +1,87 @@ +classdef DocMakerTask < matlab.buildtool.Task + %DOCMAKERTASK Generate toolbox documentation using DocMaker. + % + % See also docconvert, docrun, docindex + + properties + % Documentation theme. + DocTheme(1, 1) string {mustBeMember( DocTheme, ... + ["light", "dark", "auto"] )} = "auto" + % Stylesheets to include. + Stylesheets(1, :) string {mustBeFile} + % Scripts to include. + Scripts(1, :) string {mustBeFile} + % Root folder for publishing. + Root(1, 1) string {mustBeFolder} + % Renderer for LaTeX expressions. + MathRenderer(1, 1) string {mustBeMember( MathRenderer, ... + ["GitHub", "GitLab", "auto", "none"] )} = "none" + % Batching level. + Level(1, 1) double {mustBeInteger, ... + mustBeInRange( Level, 0, 7 )} = 0 + % Figure theme. + FigureTheme {docmaker.mustBeTheme( FigureTheme )} = "none" + % Figure size. + FigureSize(1, 2) double {mustBePositive, mustBeReal} = ... + docmaker.getDefaultFigureSize() + end % properties + + properties ( TaskInput ) + % Documentation files, in Markdown format. + MarkdownFiles(1, :) matlab.buildtool.io.FileCollection + end % properties ( TaskInput ) + + properties ( TaskOutput, SetAccess = private ) + % Documentation files, in HTML format. + HTMLFiles(1, :) matlab.buildtool.io.FileCollection + % Table of contents and doc metadata: helptoc.xml and info.xml. + XMLFiles(1, :) matlab.buildtool.io.FileCollection + % Documentation resources folder. + Resources(1, :) matlab.buildtool.io.FileCollection + % Documentation search index. + HelpSearchIndex(1, :) matlab.buildtool.io.FileCollection + end % properties ( TaskOutput, SetAccess = private ) + + methods + + function task = DocMakerTask( markdownFiles, namedArgs ) + %DOCMAKERTASK + + arguments ( Input, Repeating ) + markdownFiles + end % arguments ( Input, Repeating ) + + arguments ( Input ) + namedArgs.?DocMakerTask + end % arguments ( Input ) + + task.MarkdownFiles = markdownFiles; + task.Name = "doc"; + task.Description = ... + "Generate toolbox documentation using DocMaker"; + + + + end % constructor + + function outputArg = method1(obj,inputArg) + %METHOD1 undefined + % undefined + outputArg = obj.Property1 + inputArg; + end + end + + methods ( TaskAction ) + + + end % methods ( TaskAction ) + +end % classdef + +function s = getDefaultFigureSize() +%getDefaultFigureSize Default figure size + +p = get( 0, "DefaultFigurePosition" ); % [x y w h] +s = p(3:4); % [w h] + +end % getDefaultFigureSize \ No newline at end of file diff --git a/tbx/docmaker/docrun.m b/tbx/docmaker/docrun.m index d9c9a63..d98414f 100644 --- a/tbx/docmaker/docrun.m +++ b/tbx/docmaker/docrun.m @@ -39,8 +39,8 @@ arguments options.Level (1,1) double {mustBeInteger,mustBeInRange(options.Level,0,7)} = 0 - options.Theme {mustBeTheme(options.Theme)} = "none" - options.FigureSize (1,2) double {mustBePositive,mustBeReal} = getDefaultFigureSize() + options.Theme {docmaker.mustBeTheme(options.Theme)} = "none" + options.FigureSize (1,2) double {mustBePositive,mustBeReal} = docmaker.getDefaultFigureSize() end % Validate inputs @@ -404,23 +404,4 @@ function runDiv( div, w, theme ) "px; height: auto" ); % apply display scaling picture.appendChild( img ); -end % createResponsiveImage - -function mustBeTheme( theme ) -%mustBeTheme Validation function for optional named argument Theme - -themes = ["none","light","dark","auto"]; -assert( ( ischar( theme ) && ismember( theme, themes ) ) || ... - ( isstring( theme ) && isscalar( theme ) && ismember( theme, themes ) ) || ... - ( isa( theme, "matlab.graphics.theme.GraphicsTheme" ) && isscalar( theme ) ), ... - "Theme must be ""none"", ""light"", ""dark"", ""auto"", or a GraphicsTheme." ) - -end % mustBeTheme - -function s = getDefaultFigureSize() -%getDefaultFigureSize Default figure size - -p = get( 0, "DefaultFigurePosition" ); % [x y w h] -s = p(3:4); % [w h] - -end % getDefaultFigureSize \ No newline at end of file +end % createResponsiveImage \ No newline at end of file From 638a4ff91bc78ff683a313614432e4e5c454ed33 Mon Sep 17 00:00:00 2001 From: Ken Deeley Date: Fri, 29 May 2026 12:23:06 +0100 Subject: [PATCH 2/3] Updated custom task --- tbx/docmaker/DocMakerTask.m | 80 +++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/tbx/docmaker/DocMakerTask.m b/tbx/docmaker/DocMakerTask.m index 93c8726..f1fbb2b 100644 --- a/tbx/docmaker/DocMakerTask.m +++ b/tbx/docmaker/DocMakerTask.m @@ -12,7 +12,7 @@ % Scripts to include. Scripts(1, :) string {mustBeFile} % Root folder for publishing. - Root(1, 1) string {mustBeFolder} + Root(1, :) string {mustBeFolder, mustBeScalarOrEmpty} % Renderer for LaTeX expressions. MathRenderer(1, 1) string {mustBeMember( MathRenderer, ... ["GitHub", "GitLab", "auto", "none"] )} = "none" @@ -27,61 +27,83 @@ end % properties properties ( TaskInput ) - % Documentation files, in Markdown format. - MarkdownFiles(1, :) matlab.buildtool.io.FileCollection + % Folder containing documentation files in Markdown format. + MarkdownFolder(1, :) matlab.buildtool.io.FileCollection end % properties ( TaskInput ) properties ( TaskOutput, SetAccess = private ) % Documentation files, in HTML format. - HTMLFiles(1, :) matlab.buildtool.io.FileCollection + HTMLFiles(1, :) matlab.buildtool.io.FileCollection % Table of contents and doc metadata: helptoc.xml and info.xml. XMLFiles(1, :) matlab.buildtool.io.FileCollection % Documentation resources folder. Resources(1, :) matlab.buildtool.io.FileCollection % Documentation search index. HelpSearchIndex(1, :) matlab.buildtool.io.FileCollection - end % properties ( TaskOutput, SetAccess = private ) + end % properties ( TaskOutput, SetAccess = private ) methods - function task = DocMakerTask( markdownFiles, namedArgs ) - %DOCMAKERTASK - - arguments ( Input, Repeating ) - markdownFiles - end % arguments ( Input, Repeating ) + function task = DocMakerTask( markdownFolder, namedArgs ) + %DOCMAKERTASK Construct the DocMaker build task. arguments ( Input ) + markdownFolder namedArgs.?DocMakerTask end % arguments ( Input ) - task.MarkdownFiles = markdownFiles; - task.Name = "doc"; + % Assign the markdown folder and task outputs. + task.MarkdownFolder = markdownFolder; + task.HTMLFiles = fullfile( markdownFolder, "**", "*.html" ); + task.XMLFiles = fullfile( markdownFolder, "*.xml" ); + task.Resources = fullfile( markdownFolder, "resources" ); + task.HelpSearchIndex = ... + fullfile( markdownFolder, "helpsearch-v*" ); + + % Add the task metadata. task.Description = ... "Generate toolbox documentation using DocMaker"; + % Assign any user-specified properties. + props = string( fieldnames( namedArgs ).' ); + for prop = props + task.(prop) = namedArgs.(prop); + end % for - end % constructor - function outputArg = method1(obj,inputArg) - %METHOD1 undefined - % undefined - outputArg = obj.Property1 + inputArg; - end - end + end % methods methods ( TaskAction ) + function buildDoc( task, ~ ) + %BUILDDOC Build the toolbox documentation. + % + % * Convert Markdown documents to HTML + % * Run MATLAB code in HTML documents and insert output + % * Create info.xml and helptoc.xml from helptoc.md + + markdownFolder = task.MarkdownFolder.paths(); + markdownFiles = fullfile( markdownFolder, "**", "*.md" ); + html = docconvert( markdownFiles, ... + "Theme", task.DocTheme, ... + "Stylesheets", task.Stylesheets, ... + "Scripts", task.Scripts, ... + "Root", task.Root, ... + "MathRenderer", task.MathRenderer ); + fprintf( 1, "** Converted Markdown doc to HTML\n" ) + + docrun( html, ... + "Level", task.Level, ... + "Theme", task.FigureTheme, ... + "FigureSize", task.FigureSize ) + fprintf( 1, "** Inserted MATLAB output into doc\n" ) + + docindex( markdownFolder ) + fprintf( 1, "** Indexed doc\n" ) + + end % buildDoc end % methods ( TaskAction ) -end % classdef - -function s = getDefaultFigureSize() -%getDefaultFigureSize Default figure size - -p = get( 0, "DefaultFigurePosition" ); % [x y w h] -s = p(3:4); % [w h] - -end % getDefaultFigureSize \ No newline at end of file +end % classdef \ No newline at end of file From ee3089516bd903698d301d8bda86e21f0318251e Mon Sep 17 00:00:00 2001 From: Ken Deeley Date: Tue, 2 Jun 2026 11:50:03 +0100 Subject: [PATCH 3/3] Added Interpreter option to DocMakerTask --- tbx/docmaker/DocMakerTask.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tbx/docmaker/DocMakerTask.m b/tbx/docmaker/DocMakerTask.m index f1fbb2b..24b7970 100644 --- a/tbx/docmaker/DocMakerTask.m +++ b/tbx/docmaker/DocMakerTask.m @@ -13,6 +13,9 @@ Scripts(1, :) string {mustBeFile} % Root folder for publishing. Root(1, :) string {mustBeFolder, mustBeScalarOrEmpty} + % LaTeX interpreter. + Interpreter(1, 1) string {mustBeMember( Interpreter, ... + ["latex", "none"] )} = "none" % Renderer for LaTeX expressions. MathRenderer(1, 1) string {mustBeMember( MathRenderer, ... ["GitHub", "GitLab", "auto", "none"] )} = "none" @@ -90,6 +93,7 @@ function buildDoc( task, ~ ) "Stylesheets", task.Stylesheets, ... "Scripts", task.Scripts, ... "Root", task.Root, ... + "Interpreter", task.Interpreter, ... "MathRenderer", task.MathRenderer ); fprintf( 1, "** Converted Markdown doc to HTML\n" )