pict-docuserve 0.0.28 → 0.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -52,14 +52,14 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
52
52
  1: [function (require, module, exports) {
53
53
  module.exports = {
54
54
  "name": "fable-serviceproviderbase",
55
- "version": "3.0.18",
55
+ "version": "3.0.19",
56
56
  "description": "Simple base classes for fable services.",
57
57
  "main": "source/Fable-ServiceProviderBase.js",
58
58
  "scripts": {
59
59
  "start": "node source/Fable-ServiceProviderBase.js",
60
- "test": "npx mocha -u tdd -R spec",
61
- "tests": "npx mocha -u tdd --exit -R spec --grep",
62
- "coverage": "npx nyc --reporter=lcov --reporter=text-lcov npx mocha -- -u tdd -R spec",
60
+ "test": "npx quack test",
61
+ "tests": "npx quack test -g",
62
+ "coverage": "npx quack coverage",
63
63
  "build": "npx quack build",
64
64
  "types": "tsc -p ./tsconfig.build.json",
65
65
  "check": "tsc -p . --noEmit"
@@ -89,8 +89,8 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
89
89
  "homepage": "https://github.com/stevenvelozo/fable-serviceproviderbase",
90
90
  "devDependencies": {
91
91
  "@types/mocha": "^10.0.10",
92
- "fable": "^3.1.55",
93
- "quackage": "^1.0.51",
92
+ "fable": "^3.1.62",
93
+ "quackage": "^1.0.58",
94
94
  "typescript": "^5.9.3"
95
95
  }
96
96
  };
@@ -3228,18 +3228,18 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
3228
3228
  4: [function (require, module, exports) {
3229
3229
  module.exports = {
3230
3230
  "name": "pict-application",
3231
- "version": "1.0.32",
3231
+ "version": "1.0.33",
3232
3232
  "description": "Application base class for a pict view-based application",
3233
3233
  "main": "source/Pict-Application.js",
3234
3234
  "scripts": {
3235
- "test": "npx mocha -u tdd -R spec",
3235
+ "test": "npx quack test",
3236
3236
  "start": "node source/Pict-Application.js",
3237
- "coverage": "npx nyc --reporter=lcov --reporter=text-lcov npx mocha -- -u tdd -R spec",
3237
+ "coverage": "npx quack coverage",
3238
3238
  "build": "npx quack build",
3239
3239
  "docker-dev-build": "docker build ./ -f Dockerfile_LUXURYCode -t pict-application-image:local",
3240
3240
  "docker-dev-run": "docker run -it -d --name pict-application-dev -p 30001:8080 -p 38086:8086 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/pict-application\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" pict-application-image:local",
3241
3241
  "docker-dev-shell": "docker exec -it pict-application-dev /bin/bash",
3242
- "tests": "npx mocha -u tdd --exit -R spec --grep",
3242
+ "tests": "npx quack test -g",
3243
3243
  "lint": "eslint source/**",
3244
3244
  "types": "tsc -p ."
3245
3245
  },
@@ -3261,7 +3261,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
3261
3261
  "pict": "^1.0.348",
3262
3262
  "pict-provider": "^1.0.10",
3263
3263
  "pict-view": "^1.0.66",
3264
- "quackage": "^1.0.51",
3264
+ "quackage": "^1.0.58",
3265
3265
  "typescript": "^5.9.3"
3266
3266
  },
3267
3267
  "mocha": {
@@ -3276,7 +3276,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
3276
3276
  "watch-ignore": ["lib/vendor"]
3277
3277
  },
3278
3278
  "dependencies": {
3279
- "fable-serviceproviderbase": "^3.0.18"
3279
+ "fable-serviceproviderbase": "^3.0.19"
3280
3280
  }
3281
3281
  };
3282
3282
  }, {}],
@@ -4518,14 +4518,14 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
4518
4518
  6: [function (require, module, exports) {
4519
4519
  module.exports = {
4520
4520
  "name": "pict-provider",
4521
- "version": "1.0.10",
4521
+ "version": "1.0.12",
4522
4522
  "description": "Pict Provider Base Class",
4523
4523
  "main": "source/Pict-Provider.js",
4524
4524
  "scripts": {
4525
4525
  "start": "node source/Pict-Provider.js",
4526
- "test": "npx mocha -u tdd -R spec",
4527
- "tests": "npx mocha -u tdd --exit -R spec --grep",
4528
- "coverage": "npx nyc --reporter=lcov --reporter=text-lcov npx mocha -- -u tdd -R spec",
4526
+ "test": "npx quack test",
4527
+ "tests": "npx quack test -g",
4528
+ "coverage": "npx quack coverage",
4529
4529
  "build": "npx quack build",
4530
4530
  "docker-dev-build": "docker build ./ -f Dockerfile_LUXURYCode -t pict-provider-image:local",
4531
4531
  "docker-dev-run": "docker run -it -d --name pict-provider-dev -p 24125:8080 -p 30027:8086 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/pict-provider\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" pict-provider-image:local",
@@ -4547,12 +4547,12 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
4547
4547
  "devDependencies": {
4548
4548
  "@eslint/js": "^9.39.1",
4549
4549
  "eslint": "^9.39.1",
4550
- "pict": "^1.0.348",
4551
- "quackage": "^1.0.51",
4550
+ "pict": "^1.0.351",
4551
+ "quackage": "^1.0.58",
4552
4552
  "typescript": "^5.9.3"
4553
4553
  },
4554
4554
  "dependencies": {
4555
- "fable-serviceproviderbase": "^3.0.18"
4555
+ "fable-serviceproviderbase": "^3.0.19"
4556
4556
  },
4557
4557
  "mocha": {
4558
4558
  "diff": true,
@@ -4577,6 +4577,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
4577
4577
  AutoInitialize: true,
4578
4578
  AutoInitializeOrdinal: 0,
4579
4579
  AutoLoadDataWithApp: true,
4580
+ AutoLoadDataOrdinal: 0,
4580
4581
  AutoSolveWithApp: true,
4581
4582
  AutoSolveOrdinal: 0,
4582
4583
  Manifests: {},
@@ -4859,6 +4860,664 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
4859
4860
  "fable-serviceproviderbase": 2
4860
4861
  }],
4861
4862
  8: [function (require, module, exports) {
4863
+ /**
4864
+ * Simple syntax highlighter for use with CodeJar.
4865
+ *
4866
+ * Provides basic keyword/string/number/comment highlighting for common languages.
4867
+ * Can be replaced with Prism.js or highlight.js for more sophisticated highlighting
4868
+ * by passing a custom highlight function to the view options.
4869
+ *
4870
+ * @module Pict-Code-Highlighter
4871
+ */
4872
+
4873
+ // Language definition map
4874
+ const _LanguageDefinitions = {
4875
+ 'javascript': {
4876
+ // Combined regex to tokenize: comments, strings, template literals, regex, then everything else
4877
+ tokenizer: /(\/\/[^\n]*|\/\*[\s\S]*?\*\/)|(["'])(?:(?!\2|\\).|\\.)*?\2|(`(?:[^`\\]|\\.)*?`)|(\/(?![/*])(?:\\.|\[(?:\\.|[^\]])*\]|[^/\\\n])+\/[gimsuvy]*)/g,
4878
+ keywords: /\b(async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|export|extends|finally|for|from|function|get|if|import|in|instanceof|let|new|of|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/g,
4879
+ builtins: /\b(true|false|null|undefined|NaN|Infinity|console|window|document|Math|JSON|Array|Object|String|Number|Boolean|Date|RegExp|Map|Set|Promise|Error|Symbol|parseInt|parseFloat|require|module|exports)\b/g,
4880
+ numbers: /\b(\d+\.?\d*(?:e[+-]?\d+)?|0x[0-9a-fA-F]+|0b[01]+|0o[0-7]+)\b/g
4881
+ },
4882
+ 'json': {
4883
+ tokenizer: /(\/\/[^\n]*|\/\*[\s\S]*?\*\/)|("(?:[^"\\]|\\.)*")/g,
4884
+ keywords: /\b(true|false|null)\b/g,
4885
+ numbers: /-?\b\d+\.?\d*(?:e[+-]?\d+)?\b/g
4886
+ },
4887
+ 'html': {
4888
+ // Tokenizer captures: (1) comments, (2) strings, (3) tags with attributes
4889
+ tokenizer: /(<!--[\s\S]*?-->)|(["'])(?:(?!\2|\\).|\\.)*?\2|(<\/?[a-zA-Z][a-zA-Z0-9-]*(?:\s+[a-zA-Z-]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]*))?)*\s*\/?>)/g,
4890
+ // tagToken group index for identifying tag matches
4891
+ tagGroupIndex: 3
4892
+ },
4893
+ 'css': {
4894
+ tokenizer: /(\/\*[\s\S]*?\*\/)|(["'])(?:(?!\2|\\).|\\.)*?\2/g,
4895
+ selectors: /([.#]?[a-zA-Z_][\w-]*(?:\s*[>+~]\s*[.#]?[a-zA-Z_][\w-]*)*)\s*\{/g,
4896
+ properties: /\b([a-zA-Z-]+)\s*:/g,
4897
+ numbers: /\b(\d+\.?\d*)(px|em|rem|%|vh|vw|s|ms|deg|fr)?\b/g,
4898
+ keywords: /\b(important|inherit|initial|unset|none|auto|block|inline|flex|grid)\b/g
4899
+ },
4900
+ 'sql': {
4901
+ tokenizer: /(--[^\n]*|\/\*[\s\S]*?\*\/)|(["'])(?:(?!\2|\\).|\\.)*?\2/g,
4902
+ keywords: /\b(SELECT|FROM|WHERE|AND|OR|INSERT|INTO|VALUES|UPDATE|SET|DELETE|CREATE|TABLE|DROP|ALTER|ADD|COLUMN|INDEX|JOIN|LEFT|RIGHT|INNER|OUTER|ON|AS|ORDER|BY|GROUP|HAVING|LIMIT|OFFSET|UNION|ALL|DISTINCT|COUNT|SUM|AVG|MIN|MAX|NOT|NULL|IS|IN|BETWEEN|LIKE|EXISTS|CASE|WHEN|THEN|ELSE|END|PRIMARY|KEY|FOREIGN|REFERENCES|CONSTRAINT|DEFAULT|CHECK|UNIQUE|CASCADE|GRANT|REVOKE|COMMIT|ROLLBACK|BEGIN|TRANSACTION|INT|VARCHAR|DATETIME|AUTO_INCREMENT|CURRENT_TIMESTAMP)\b/gi,
4903
+ numbers: /\b\d+\.?\d*\b/g
4904
+ }
4905
+ };
4906
+
4907
+ // Alias some common language names
4908
+ _LanguageDefinitions['js'] = _LanguageDefinitions['javascript'];
4909
+ _LanguageDefinitions['htm'] = _LanguageDefinitions['html'];
4910
+
4911
+ /**
4912
+ * Escape HTML special characters to prevent XSS when inserting into innerHTML.
4913
+ *
4914
+ * @param {string} pString - The string to escape
4915
+ * @returns {string} The escaped string
4916
+ */
4917
+ function escapeHTML(pString) {
4918
+ return pString.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
4919
+ }
4920
+
4921
+ /**
4922
+ * Highlight a segment of code that is NOT inside a string or comment.
4923
+ * This applies keyword, number, and structural highlighting.
4924
+ *
4925
+ * @param {string} pCode - The code segment to highlight (already HTML-escaped)
4926
+ * @param {object} pLanguageDef - The language definition
4927
+ * @returns {string} The highlighted HTML
4928
+ */
4929
+ function highlightCodeSegment(pCode, pLanguageDef) {
4930
+ let tmpResult = pCode;
4931
+
4932
+ // CSS selectors
4933
+ if (pLanguageDef.selectors) {
4934
+ pLanguageDef.selectors.lastIndex = 0;
4935
+ tmpResult = tmpResult.replace(pLanguageDef.selectors, '<span class="function-name">$1</span>{');
4936
+ }
4937
+
4938
+ // CSS properties
4939
+ if (pLanguageDef.properties) {
4940
+ pLanguageDef.properties.lastIndex = 0;
4941
+ tmpResult = tmpResult.replace(pLanguageDef.properties, '<span class="property">$1</span>:');
4942
+ }
4943
+
4944
+ // Keywords
4945
+ if (pLanguageDef.keywords) {
4946
+ pLanguageDef.keywords.lastIndex = 0;
4947
+ tmpResult = tmpResult.replace(pLanguageDef.keywords, '<span class="keyword">$1</span>');
4948
+ }
4949
+
4950
+ // Builtins
4951
+ if (pLanguageDef.builtins) {
4952
+ pLanguageDef.builtins.lastIndex = 0;
4953
+ tmpResult = tmpResult.replace(pLanguageDef.builtins, '<span class="keyword">$1</span>');
4954
+ }
4955
+
4956
+ // Numbers (CSS numbers may have units as a capture group, others do not)
4957
+ if (pLanguageDef.numbers) {
4958
+ pLanguageDef.numbers.lastIndex = 0;
4959
+ tmpResult = tmpResult.replace(pLanguageDef.numbers, pMatch => {
4960
+ return "<span class=\"number\">".concat(pMatch, "</span>");
4961
+ });
4962
+ }
4963
+ return tmpResult;
4964
+ }
4965
+
4966
+ /**
4967
+ * Highlight an HTML tag token, applying tag name, attribute name, and attribute value colors.
4968
+ *
4969
+ * The approach: parse the raw tag into structured pieces first, then build the
4970
+ * highlighted output from those pieces. This avoids mixing raw text with HTML span
4971
+ * tags, which would cause regex replacements to match span attributes on subsequent passes.
4972
+ *
4973
+ * @param {string} pTag - The raw (unescaped) tag string
4974
+ * @returns {string} The highlighted HTML
4975
+ */
4976
+ function highlightHTMLTag(pTag) {
4977
+ let tmpResult = '';
4978
+ let tmpRest = pTag;
4979
+
4980
+ // 1. Extract the opening bracket and tag name: < or </ followed by tagname
4981
+ let tmpTagNameMatch = tmpRest.match(/^(<\/?)([a-zA-Z][a-zA-Z0-9-]*)/);
4982
+ if (!tmpTagNameMatch) {
4983
+ // Not a recognizable tag, just escape the whole thing
4984
+ return escapeHTML(pTag);
4985
+ }
4986
+ tmpResult += escapeHTML(tmpTagNameMatch[1]);
4987
+ tmpResult += '<span class="tag">' + escapeHTML(tmpTagNameMatch[2]) + '</span>';
4988
+ tmpRest = tmpRest.substring(tmpTagNameMatch[0].length);
4989
+
4990
+ // 2. Parse attributes from the remaining text (before the closing > or />)
4991
+ // Repeatedly match: whitespace + attr-name + optional =value
4992
+ let tmpAttrRegex = /^(\s+)([a-zA-Z-]+)(?:(\s*=\s*)(["'])([^"']*?)\4)?/;
4993
+ let tmpAttrMatch;
4994
+ while ((tmpAttrMatch = tmpRest.match(tmpAttrRegex)) !== null) {
4995
+ // Whitespace before the attribute
4996
+ tmpResult += tmpAttrMatch[1];
4997
+ // Attribute name
4998
+ tmpResult += '<span class="attr-name">' + escapeHTML(tmpAttrMatch[2]) + '</span>';
4999
+
5000
+ // If there's an = value part
5001
+ if (tmpAttrMatch[3]) {
5002
+ tmpResult += escapeHTML(tmpAttrMatch[3]);
5003
+ tmpResult += '<span class="attr-value">' + escapeHTML(tmpAttrMatch[4]) + escapeHTML(tmpAttrMatch[5]) + escapeHTML(tmpAttrMatch[4]) + '</span>';
5004
+ }
5005
+ tmpRest = tmpRest.substring(tmpAttrMatch[0].length);
5006
+ }
5007
+
5008
+ // 3. Whatever remains (whitespace, />, >) — escape it all
5009
+ tmpResult += escapeHTML(tmpRest);
5010
+ return tmpResult;
5011
+ }
5012
+
5013
+ /**
5014
+ * Create a highlight function for a given language.
5015
+ *
5016
+ * The approach: use a single tokenizer regex to split the code into protected tokens
5017
+ * (comments, strings) and code segments. Process each segment independently.
5018
+ * This avoids placeholder/sentinel issues entirely.
5019
+ *
5020
+ * @param {string} pLanguage - The language identifier (e.g. "javascript", "json", "html")
5021
+ * @returns {function} A function that takes an element and highlights its textContent
5022
+ */
5023
+ function createHighlighter(pLanguage) {
5024
+ return function highlightElement(pElement) {
5025
+ let tmpCode = pElement.textContent;
5026
+ let tmpLanguageName = typeof pLanguage === 'string' ? pLanguage.toLowerCase() : 'javascript';
5027
+ let tmpLanguageDef = _LanguageDefinitions[tmpLanguageName];
5028
+ if (!tmpLanguageDef) {
5029
+ // No highlighting rules for this language; just escape and return
5030
+ pElement.innerHTML = escapeHTML(tmpCode);
5031
+ return;
5032
+ }
5033
+ if (!tmpLanguageDef.tokenizer) {
5034
+ // No tokenizer; just escape and apply keyword highlighting
5035
+ pElement.innerHTML = highlightCodeSegment(escapeHTML(tmpCode), tmpLanguageDef);
5036
+ return;
5037
+ }
5038
+
5039
+ // Split the code into tokens using the tokenizer regex.
5040
+ // The tokenizer captures comments and strings as groups.
5041
+ // We process everything between matches as code.
5042
+ let tmpResult = '';
5043
+ let tmpLastIndex = 0;
5044
+ let tmpTagGroupIndex = tmpLanguageDef.tagGroupIndex || 0;
5045
+ tmpLanguageDef.tokenizer.lastIndex = 0;
5046
+ let tmpMatch;
5047
+ while ((tmpMatch = tmpLanguageDef.tokenizer.exec(tmpCode)) !== null) {
5048
+ // Add the code segment before this match
5049
+ if (tmpMatch.index > tmpLastIndex) {
5050
+ let tmpSegment = tmpCode.substring(tmpLastIndex, tmpMatch.index);
5051
+ tmpResult += highlightCodeSegment(escapeHTML(tmpSegment), tmpLanguageDef);
5052
+ }
5053
+ let tmpFullMatch = tmpMatch[0];
5054
+
5055
+ // Determine token type from capture groups
5056
+ // Group 1 is always comments, Group 2+ are strings/template literals/regex
5057
+ if (tmpMatch[1]) {
5058
+ // Comment
5059
+ tmpResult += "<span class=\"comment\">".concat(escapeHTML(tmpFullMatch), "</span>");
5060
+ } else if (tmpTagGroupIndex > 0 && tmpMatch[tmpTagGroupIndex]) {
5061
+ // HTML tag — highlight tag name, attributes, and values
5062
+ tmpResult += highlightHTMLTag(tmpFullMatch);
5063
+ } else {
5064
+ // String, template literal, or regex
5065
+ tmpResult += "<span class=\"string\">".concat(escapeHTML(tmpFullMatch), "</span>");
5066
+ }
5067
+ tmpLastIndex = tmpLanguageDef.tokenizer.lastIndex;
5068
+ }
5069
+
5070
+ // Add any remaining code after the last match
5071
+ if (tmpLastIndex < tmpCode.length) {
5072
+ let tmpSegment = tmpCode.substring(tmpLastIndex);
5073
+ tmpResult += highlightCodeSegment(escapeHTML(tmpSegment), tmpLanguageDef);
5074
+ }
5075
+ pElement.innerHTML = tmpResult;
5076
+ };
5077
+ }
5078
+ module.exports = createHighlighter;
5079
+ module.exports.LanguageDefinitions = _LanguageDefinitions;
5080
+ }, {}],
5081
+ 9: [function (require, module, exports) {
5082
+ module.exports = {
5083
+ "RenderOnLoad": true,
5084
+ "DefaultRenderable": "CodeEditor-Wrap",
5085
+ "DefaultDestinationAddress": "#CodeEditor-Container-Div",
5086
+ "Templates": [{
5087
+ "Hash": "CodeEditor-Container",
5088
+ "Template": "<!-- CodeEditor-Container Rendering Soon -->"
5089
+ }],
5090
+ "Renderables": [{
5091
+ "RenderableHash": "CodeEditor-Wrap",
5092
+ "TemplateHash": "CodeEditor-Container",
5093
+ "DestinationAddress": "#CodeEditor-Container-Div"
5094
+ }],
5095
+ "TargetElementAddress": "#CodeEditor-Container-Div",
5096
+ // Address in AppData or other Pict address space to read/write code content
5097
+ "CodeDataAddress": false,
5098
+ // The language for syntax highlighting (e.g. "javascript", "html", "css", "json")
5099
+ "Language": "javascript",
5100
+ // Whether the editor is read-only
5101
+ "ReadOnly": false,
5102
+ // Tab character: use tab or spaces
5103
+ "Tab": "\t",
5104
+ // Whether to indent with the same whitespace as the previous line
5105
+ "IndentOn": /[({[]$/,
5106
+ // Whether to add a closing bracket/paren/brace
5107
+ "MoveToNewLine": /^[)}\]]/,
5108
+ // Whether to handle the closing character
5109
+ "AddClosing": true,
5110
+ // Whether to preserve indentation on new lines
5111
+ "CatchTab": true,
5112
+ // Whether to show line numbers
5113
+ "LineNumbers": true,
5114
+ // Default code content if no address is provided
5115
+ "DefaultCode": "// Enter your code here\n",
5116
+ // CSS for the code editor
5117
+ "CSS": ".pict-code-editor-wrap\n{\n\tdisplay: flex;\n\tfont-family: 'SFMono-Regular', 'SF Mono', 'Menlo', 'Consolas', 'Liberation Mono', 'Courier New', monospace;\n\tfont-size: 14px;\n\tline-height: 1.5;\n\tborder: 1px solid #D0D0D0;\n\tborder-radius: 4px;\n\toverflow: auto;\n}\n.pict-code-editor-wrap .pict-code-line-numbers\n{\n\tposition: sticky;\n\tleft: 0;\n\twidth: 40px;\n\tmin-width: 40px;\n\tpadding: 10px 0;\n\ttext-align: right;\n\tbackground: #F5F5F5;\n\tborder-right: 1px solid #D0D0D0;\n\tcolor: #999;\n\tfont-size: 13px;\n\tline-height: 1.5;\n\tuser-select: none;\n\tpointer-events: none;\n\tbox-sizing: border-box;\n\tz-index: 1;\n}\n.pict-code-editor-wrap .pict-code-line-numbers span\n{\n\tdisplay: block;\n\tpadding: 0 8px 0 0;\n}\n.pict-code-editor-wrap .pict-code-editor\n{\n\tmargin: 0;\n\tpadding: 10px 10px 10px 8px;\n\tmin-height: 100px;\n\tflex: 1;\n\tmin-width: 0;\n\toutline: none;\n\ttab-size: 4;\n\twhite-space: pre;\n\toverflow-wrap: normal;\n\tcolor: #383A42;\n\tbackground: #FAFAFA;\n\tcaret-color: #526FFF;\n\tborder-radius: 0 4px 4px 0;\n}\n.pict-code-editor-wrap .pict-code-editor.pict-code-no-line-numbers\n{\n\tpadding-left: 10px;\n\tborder-radius: 4px;\n}\n.pict-code-editor-wrap .pict-code-editor .keyword { color: #A626A4; }\n.pict-code-editor-wrap .pict-code-editor .string { color: #50A14F; }\n.pict-code-editor-wrap .pict-code-editor .number { color: #986801; }\n.pict-code-editor-wrap .pict-code-editor .comment { color: #A0A1A7; font-style: italic; }\n.pict-code-editor-wrap .pict-code-editor .operator { color: #0184BC; }\n.pict-code-editor-wrap .pict-code-editor .punctuation { color: #383A42; }\n.pict-code-editor-wrap .pict-code-editor .function-name { color: #4078F2; }\n.pict-code-editor-wrap .pict-code-editor .property { color: #E45649; }\n.pict-code-editor-wrap .pict-code-editor .tag { color: #E45649; }\n.pict-code-editor-wrap .pict-code-editor .attr-name { color: #986801; }\n.pict-code-editor-wrap .pict-code-editor .attr-value { color: #50A14F; }\n"
5118
+ };
5119
+ }, {}],
5120
+ 10: [function (require, module, exports) {
5121
+ const libPictViewClass = require('pict-view');
5122
+ const libCreateHighlighter = require('./Pict-Code-Highlighter.js');
5123
+ const _DefaultConfiguration = require('./Pict-Section-Code-DefaultConfiguration.js');
5124
+ class PictSectionCode extends libPictViewClass {
5125
+ constructor(pFable, pOptions, pServiceHash) {
5126
+ let tmpOptions = Object.assign({}, _DefaultConfiguration, pOptions);
5127
+ super(pFable, tmpOptions, pServiceHash);
5128
+ this.initialRenderComplete = false;
5129
+
5130
+ // The CodeJar instance
5131
+ this.codeJar = null;
5132
+
5133
+ // The highlight function (can be overridden)
5134
+ this._highlightFunction = null;
5135
+
5136
+ // The current language
5137
+ this._language = this.options.Language || 'javascript';
5138
+ }
5139
+ onBeforeInitialize() {
5140
+ super.onBeforeInitialize();
5141
+ this._codeJarPrototype = null;
5142
+ this.targetElement = false;
5143
+
5144
+ // Build the default highlight function for the configured language
5145
+ this._highlightFunction = libCreateHighlighter(this._language);
5146
+ return super.onBeforeInitialize();
5147
+ }
5148
+
5149
+ /**
5150
+ * Connect the CodeJar prototype. If not passed explicitly, try to find it
5151
+ * as a global (window.CodeJar) or require it from the npm package.
5152
+ *
5153
+ * @param {function} [pCodeJarPrototype] - The CodeJar constructor function
5154
+ * @returns {boolean|void}
5155
+ */
5156
+ connectCodeJarPrototype(pCodeJarPrototype) {
5157
+ if (typeof pCodeJarPrototype === 'function') {
5158
+ this._codeJarPrototype = pCodeJarPrototype;
5159
+ return;
5160
+ }
5161
+
5162
+ // Try to find CodeJar in global scope
5163
+ if (typeof window !== 'undefined') {
5164
+ if (typeof window.CodeJar === 'function') {
5165
+ this.log.trace("PICT-Code Found CodeJar in window.CodeJar.");
5166
+ this._codeJarPrototype = window.CodeJar;
5167
+ return;
5168
+ }
5169
+ }
5170
+ this.log.error("PICT-Code No CodeJar prototype found. Include codejar via script tag or call connectCodeJarPrototype(CodeJar) explicitly.");
5171
+ return false;
5172
+ }
5173
+ onAfterRender(pRenderable) {
5174
+ // Ensure the CSS from all registered views is injected into the DOM
5175
+ this.pict.CSSMap.injectCSS();
5176
+ if (!this.initialRenderComplete) {
5177
+ this.onAfterInitialRender();
5178
+ this.initialRenderComplete = true;
5179
+ }
5180
+ return super.onAfterRender(pRenderable);
5181
+ }
5182
+ onAfterInitialRender() {
5183
+ // Resolve the CodeJar prototype if not already set
5184
+ if (!this._codeJarPrototype) {
5185
+ this.connectCodeJarPrototype();
5186
+ }
5187
+ if (!this._codeJarPrototype) {
5188
+ this.log.error("PICT-Code Cannot initialize editor; no CodeJar prototype available.");
5189
+ return false;
5190
+ }
5191
+ if (this.codeJar) {
5192
+ this.log.error("PICT-Code editor is already initialized!");
5193
+ return false;
5194
+ }
5195
+
5196
+ // Find the target element
5197
+ let tmpTargetElementSet = this.services.ContentAssignment.getElement(this.options.TargetElementAddress);
5198
+ if (!tmpTargetElementSet || tmpTargetElementSet.length < 1) {
5199
+ this.log.error("PICT-Code Could not find target element [".concat(this.options.TargetElementAddress, "]!"));
5200
+ this.targetElement = false;
5201
+ return false;
5202
+ }
5203
+ this.targetElement = tmpTargetElementSet[0];
5204
+
5205
+ // Build the editor DOM structure
5206
+ this._buildEditorDOM();
5207
+
5208
+ // Get initial code content
5209
+ let tmpCode = this._resolveCodeContent();
5210
+
5211
+ // Create the CodeJar options
5212
+ let tmpCodeJarOptions = {};
5213
+ if (this.options.Tab) {
5214
+ tmpCodeJarOptions.tab = this.options.Tab;
5215
+ }
5216
+ if (this.options.IndentOn) {
5217
+ tmpCodeJarOptions.indentOn = this.options.IndentOn;
5218
+ }
5219
+ if (this.options.MoveToNewLine) {
5220
+ tmpCodeJarOptions.moveToNewLine = this.options.MoveToNewLine;
5221
+ }
5222
+ if (typeof this.options.AddClosing !== 'undefined') {
5223
+ tmpCodeJarOptions.addClosing = this.options.AddClosing;
5224
+ }
5225
+ if (typeof this.options.CatchTab !== 'undefined') {
5226
+ tmpCodeJarOptions.catchTab = this.options.CatchTab;
5227
+ }
5228
+ this.customConfigureEditorOptions(tmpCodeJarOptions);
5229
+
5230
+ // Instantiate CodeJar on the editor element
5231
+ let tmpEditorElement = this._editorElement;
5232
+ this.codeJar = this._codeJarPrototype(tmpEditorElement, this._highlightFunction, tmpCodeJarOptions);
5233
+
5234
+ // CodeJar forces white-space:pre-wrap and overflow-wrap:break-word
5235
+ // via inline styles, which causes line wrapping that breaks the
5236
+ // line-number alignment. Override back to non-wrapping so the
5237
+ // wrap container scrolls horizontally instead.
5238
+ this._resetEditorWrapStyles();
5239
+
5240
+ // Set the initial code
5241
+ if (tmpCode) {
5242
+ this.codeJar.updateCode(tmpCode);
5243
+ }
5244
+
5245
+ // Wire up the change handler
5246
+ this.codeJar.onUpdate(pCode => {
5247
+ this._updateLineNumbers();
5248
+ this.onCodeChange(pCode);
5249
+ });
5250
+
5251
+ // Initial line number render
5252
+ this._updateLineNumbers();
5253
+
5254
+ // Handle read-only
5255
+ if (this.options.ReadOnly) {
5256
+ tmpEditorElement.setAttribute('contenteditable', 'false');
5257
+ }
5258
+ }
5259
+
5260
+ /**
5261
+ * Build the editor DOM elements inside the target container.
5262
+ */
5263
+ _buildEditorDOM() {
5264
+ // Clear the target
5265
+ this.targetElement.innerHTML = '';
5266
+
5267
+ // Create wrapper
5268
+ let tmpWrap = document.createElement('div');
5269
+ tmpWrap.className = 'pict-code-editor-wrap';
5270
+
5271
+ // Create line numbers container
5272
+ if (this.options.LineNumbers) {
5273
+ let tmpLineNumbers = document.createElement('div');
5274
+ tmpLineNumbers.className = 'pict-code-line-numbers';
5275
+ tmpWrap.appendChild(tmpLineNumbers);
5276
+ this._lineNumbersElement = tmpLineNumbers;
5277
+ }
5278
+
5279
+ // Create the editor element (CodeJar needs a pre or div)
5280
+ let tmpEditor = document.createElement('div');
5281
+ tmpEditor.className = 'pict-code-editor language-' + this._language;
5282
+ if (!this.options.LineNumbers) {
5283
+ tmpEditor.className += ' pict-code-no-line-numbers';
5284
+ }
5285
+ tmpWrap.appendChild(tmpEditor);
5286
+ this.targetElement.appendChild(tmpWrap);
5287
+ this._editorElement = tmpEditor;
5288
+ this._wrapElement = tmpWrap;
5289
+ }
5290
+
5291
+ /**
5292
+ * Update the line numbers display based on current code content.
5293
+ */
5294
+ _updateLineNumbers() {
5295
+ if (!this.options.LineNumbers || !this._lineNumbersElement || !this._editorElement) {
5296
+ return;
5297
+ }
5298
+ let tmpCode = this._editorElement.textContent || '';
5299
+ let tmpLineCount = tmpCode.split('\n').length;
5300
+ let tmpHTML = '';
5301
+ for (let i = 1; i <= tmpLineCount; i++) {
5302
+ tmpHTML += "<span>".concat(i, "</span>");
5303
+ }
5304
+ this._lineNumbersElement.innerHTML = tmpHTML;
5305
+ }
5306
+
5307
+ /**
5308
+ * Reset inline styles that CodeJar sets on the editor element.
5309
+ *
5310
+ * CodeJar forces white-space:pre-wrap and overflow-wrap:break-word so
5311
+ * long lines wrap visually. That breaks line-number alignment because
5312
+ * each wrapped visual row is not a logical line. Resetting to pre /
5313
+ * normal makes the outer .pict-code-editor-wrap scroll horizontally.
5314
+ */
5315
+ _resetEditorWrapStyles() {
5316
+ if (!this._editorElement) {
5317
+ return;
5318
+ }
5319
+ this._editorElement.style.whiteSpace = 'pre';
5320
+ this._editorElement.style.overflowWrap = 'normal';
5321
+ }
5322
+
5323
+ /**
5324
+ * Resolve the initial code content from address or default.
5325
+ *
5326
+ * @returns {string} The code content
5327
+ */
5328
+ _resolveCodeContent() {
5329
+ if (this.options.CodeDataAddress) {
5330
+ const tmpAddressSpace = {
5331
+ Fable: this.fable,
5332
+ Pict: this.fable,
5333
+ AppData: this.AppData,
5334
+ Bundle: this.Bundle,
5335
+ Options: this.options
5336
+ };
5337
+ let tmpAddressedData = this.fable.manifest.getValueByHash(tmpAddressSpace, this.options.CodeDataAddress);
5338
+ if (typeof tmpAddressedData === 'string') {
5339
+ return tmpAddressedData;
5340
+ } else {
5341
+ this.log.warn("PICT-Code Address [".concat(this.options.CodeDataAddress, "] did not return a string; it was ").concat(typeof tmpAddressedData, "."));
5342
+ }
5343
+ }
5344
+ return this.options.DefaultCode || '';
5345
+ }
5346
+
5347
+ /**
5348
+ * Hook for subclasses to customize CodeJar options before instantiation.
5349
+ *
5350
+ * @param {object} pOptions - The CodeJar options object to modify
5351
+ */
5352
+ customConfigureEditorOptions(pOptions) {
5353
+ // Override in subclass to tweak options
5354
+ }
5355
+
5356
+ /**
5357
+ * Called when the code content changes. Override in subclasses to handle changes.
5358
+ *
5359
+ * @param {string} pCode - The new code content
5360
+ */
5361
+ onCodeChange(pCode) {
5362
+ // Write back to data address if configured
5363
+ if (this.options.CodeDataAddress) {
5364
+ const tmpAddressSpace = {
5365
+ Fable: this.fable,
5366
+ Pict: this.fable,
5367
+ AppData: this.AppData,
5368
+ Bundle: this.Bundle,
5369
+ Options: this.options
5370
+ };
5371
+ this.fable.manifest.setValueByHash(tmpAddressSpace, this.options.CodeDataAddress, pCode);
5372
+ }
5373
+ }
5374
+
5375
+ // -- Public API Methods --
5376
+
5377
+ /**
5378
+ * Get the current code content.
5379
+ *
5380
+ * @returns {string} The current code
5381
+ */
5382
+ getCode() {
5383
+ if (!this.codeJar) {
5384
+ this.log.warn('PICT-Code getCode called before editor initialized.');
5385
+ return '';
5386
+ }
5387
+ return this.codeJar.toString();
5388
+ }
5389
+
5390
+ /**
5391
+ * Set the code content.
5392
+ *
5393
+ * @param {string} pCode - The code to set
5394
+ */
5395
+ setCode(pCode) {
5396
+ if (!this.codeJar) {
5397
+ this.log.warn('PICT-Code setCode called before editor initialized.');
5398
+ return;
5399
+ }
5400
+ this.codeJar.updateCode(pCode);
5401
+ this._updateLineNumbers();
5402
+ }
5403
+
5404
+ /**
5405
+ * Change the editor language and re-highlight.
5406
+ *
5407
+ * @param {string} pLanguage - The language identifier
5408
+ */
5409
+ setLanguage(pLanguage) {
5410
+ this._language = pLanguage;
5411
+ this._highlightFunction = libCreateHighlighter(pLanguage);
5412
+ if (this._editorElement) {
5413
+ // Update the class
5414
+ this._editorElement.className = 'pict-code-editor language-' + pLanguage;
5415
+ if (!this.options.LineNumbers) {
5416
+ this._editorElement.className += ' pict-code-no-line-numbers';
5417
+ }
5418
+ }
5419
+ if (this.codeJar) {
5420
+ // Re-create the editor with the new highlight function
5421
+ let tmpCode = this.codeJar.toString();
5422
+ this.codeJar.destroy();
5423
+ this.codeJar = this._codeJarPrototype(this._editorElement, this._highlightFunction, {
5424
+ tab: this.options.Tab,
5425
+ catchTab: this.options.CatchTab,
5426
+ addClosing: this.options.AddClosing
5427
+ });
5428
+ this._resetEditorWrapStyles();
5429
+ this.codeJar.updateCode(tmpCode);
5430
+ this.codeJar.onUpdate(pCode => {
5431
+ this._updateLineNumbers();
5432
+ this.onCodeChange(pCode);
5433
+ });
5434
+ }
5435
+ }
5436
+
5437
+ /**
5438
+ * Set a custom highlight function to replace the built-in highlighter.
5439
+ * Useful for integrating Prism.js, highlight.js, or any other library.
5440
+ *
5441
+ * @param {function} pHighlightFunction - A function that takes a DOM element and highlights its textContent
5442
+ */
5443
+ setHighlightFunction(pHighlightFunction) {
5444
+ if (typeof pHighlightFunction !== 'function') {
5445
+ this.log.error('PICT-Code setHighlightFunction requires a function.');
5446
+ return;
5447
+ }
5448
+ this._highlightFunction = pHighlightFunction;
5449
+ if (this.codeJar) {
5450
+ let tmpCode = this.codeJar.toString();
5451
+ this.codeJar.destroy();
5452
+ this.codeJar = this._codeJarPrototype(this._editorElement, this._highlightFunction, {
5453
+ tab: this.options.Tab,
5454
+ catchTab: this.options.CatchTab,
5455
+ addClosing: this.options.AddClosing
5456
+ });
5457
+ this._resetEditorWrapStyles();
5458
+ this.codeJar.updateCode(tmpCode);
5459
+ this.codeJar.onUpdate(pCode => {
5460
+ this._updateLineNumbers();
5461
+ this.onCodeChange(pCode);
5462
+ });
5463
+ }
5464
+ }
5465
+
5466
+ /**
5467
+ * Set the read-only state of the editor.
5468
+ *
5469
+ * @param {boolean} pReadOnly - Whether the editor should be read-only
5470
+ */
5471
+ setReadOnly(pReadOnly) {
5472
+ this.options.ReadOnly = pReadOnly;
5473
+ if (this._editorElement) {
5474
+ this._editorElement.setAttribute('contenteditable', pReadOnly ? 'false' : 'true');
5475
+ }
5476
+ }
5477
+
5478
+ /**
5479
+ * Destroy the editor and clean up.
5480
+ */
5481
+ destroy() {
5482
+ if (this.codeJar) {
5483
+ this.codeJar.destroy();
5484
+ this.codeJar = null;
5485
+ }
5486
+ }
5487
+
5488
+ /**
5489
+ * Marshal code content from the data address into the view.
5490
+ */
5491
+ marshalToView() {
5492
+ super.marshalToView();
5493
+ if (this.codeJar && this.options.CodeDataAddress) {
5494
+ let tmpCode = this._resolveCodeContent();
5495
+ if (typeof tmpCode === 'string') {
5496
+ this.codeJar.updateCode(tmpCode);
5497
+ this._updateLineNumbers();
5498
+ }
5499
+ }
5500
+ }
5501
+
5502
+ /**
5503
+ * Marshal the current code content back to the data address.
5504
+ */
5505
+ marshalFromView() {
5506
+ super.marshalFromView();
5507
+ if (this.codeJar && this.options.CodeDataAddress) {
5508
+ this.onCodeChange(this.codeJar.toString());
5509
+ }
5510
+ }
5511
+ }
5512
+ module.exports = PictSectionCode;
5513
+ module.exports.default_configuration = _DefaultConfiguration;
5514
+ module.exports.createHighlighter = libCreateHighlighter;
5515
+ }, {
5516
+ "./Pict-Code-Highlighter.js": 8,
5517
+ "./Pict-Section-Code-DefaultConfiguration.js": 9,
5518
+ "pict-view": 15
5519
+ }],
5520
+ 11: [function (require, module, exports) {
4862
5521
  // The container for all the Pict-Section-Content related code.
4863
5522
 
4864
5523
  // The main content view class
@@ -4867,11 +5526,12 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
4867
5526
  // The content provider (markdown parsing, HTML escaping)
4868
5527
  module.exports.PictContentProvider = require('./providers/Pict-Provider-Content.js');
4869
5528
  }, {
4870
- "./providers/Pict-Provider-Content.js": 9,
4871
- "./views/Pict-View-Content.js": 10
5529
+ "./providers/Pict-Provider-Content.js": 12,
5530
+ "./views/Pict-View-Content.js": 13
4872
5531
  }],
4873
- 9: [function (require, module, exports) {
5532
+ 12: [function (require, module, exports) {
4874
5533
  const libPictProvider = require('pict-provider');
5534
+ const libCreateHighlighter = require('pict-section-code').createHighlighter;
4875
5535
 
4876
5536
  /**
4877
5537
  * Content Provider for Pict Section Content
@@ -4879,6 +5539,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
4879
5539
  * A general-purpose markdown-to-HTML parser with support for:
4880
5540
  * - Headings, paragraphs, lists, blockquotes, horizontal rules
4881
5541
  * - Fenced code blocks with language tags (nested fence support)
5542
+ * - Syntax highlighting and line numbers for code blocks (via pict-section-code)
4882
5543
  * - Tables (GFM pipe syntax)
4883
5544
  * - Mermaid diagram blocks
4884
5545
  * - KaTeX math (inline and display)
@@ -4891,14 +5552,55 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
4891
5552
  super(pFable, pOptions, pServiceHash);
4892
5553
  }
4893
5554
 
5555
+ /**
5556
+ * Highlight a code string using pict-section-code's syntax highlighter.
5557
+ * Uses a mock element to interface with the highlighter's DOM-based API.
5558
+ *
5559
+ * @param {string} pCode - The raw code string
5560
+ * @param {string} pLanguage - The language identifier (e.g. "javascript", "html")
5561
+ * @returns {string} The syntax-highlighted HTML
5562
+ */
5563
+ highlightCode(pCode, pLanguage) {
5564
+ if (!pCode) {
5565
+ return '';
5566
+ }
5567
+ let tmpHighlighter = libCreateHighlighter(pLanguage);
5568
+ // Create a mock element to interface with the highlighter
5569
+ let tmpMockElement = {
5570
+ textContent: pCode,
5571
+ innerHTML: ''
5572
+ };
5573
+ tmpHighlighter(tmpMockElement);
5574
+ return tmpMockElement.innerHTML;
5575
+ }
5576
+
5577
+ /**
5578
+ * Generate line number HTML for a code block.
5579
+ *
5580
+ * @param {string} pCode - The raw code string
5581
+ * @returns {string} HTML string with line number spans
5582
+ */
5583
+ generateLineNumbers(pCode) {
5584
+ if (!pCode) {
5585
+ return '<span>1</span>';
5586
+ }
5587
+ let tmpLineCount = pCode.split('\n').length;
5588
+ let tmpHTML = '';
5589
+ for (let i = 1; i <= tmpLineCount; i++) {
5590
+ tmpHTML += '<span>' + i + '</span>';
5591
+ }
5592
+ return tmpHTML;
5593
+ }
5594
+
4894
5595
  /**
4895
5596
  * Parse a markdown string into HTML.
4896
5597
  *
4897
5598
  * @param {string} pMarkdown - The raw markdown text
4898
5599
  * @param {Function} [pLinkResolver] - Optional callback for link resolution: (pHref, pLinkText) => { href, target, rel } or null
5600
+ * @param {Function} [pImageResolver] - Optional callback for image URL resolution: (pSrc, pAlt) => resolvedSrc or null
4899
5601
  * @returns {string} The parsed HTML
4900
5602
  */
4901
- parseMarkdown(pMarkdown, pLinkResolver) {
5603
+ parseMarkdown(pMarkdown, pLinkResolver, pImageResolver) {
4902
5604
  if (!pMarkdown) {
4903
5605
  return '';
4904
5606
  }
@@ -4920,7 +5622,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
4920
5622
  let fFlushParagraph = () => {
4921
5623
  if (tmpParagraphLines.length > 0) {
4922
5624
  tmpHTML.push('<p>' + tmpParagraphLines.map(pLine => {
4923
- return this.parseInline(pLine, pLinkResolver);
5625
+ return this.parseInline(pLine, pLinkResolver, pImageResolver);
4924
5626
  }).join(' ') + '</p>');
4925
5627
  tmpParagraphLines = [];
4926
5628
  }
@@ -4944,7 +5646,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
4944
5646
  tmpInList = false;
4945
5647
  }
4946
5648
  if (tmpInBlockquote) {
4947
- tmpHTML.push('<blockquote>' + this.parseMarkdown(tmpBlockquoteLines.join('\n'), pLinkResolver) + '</blockquote>');
5649
+ tmpHTML.push('<blockquote>' + this.parseMarkdown(tmpBlockquoteLines.join('\n'), pLinkResolver, pImageResolver) + '</blockquote>');
4948
5650
  tmpInBlockquote = false;
4949
5651
  tmpBlockquoteLines = [];
4950
5652
  }
@@ -4969,7 +5671,10 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
4969
5671
  // Mermaid diagrams: output raw content for client-side rendering
4970
5672
  tmpHTML.push('<pre class="mermaid">' + tmpCodeLines.join('\n') + '</pre>');
4971
5673
  } else {
4972
- tmpHTML.push('<pre><code class="language-' + this.escapeHTML(tmpCodeLang) + '">' + this.escapeHTML(tmpCodeLines.join('\n')) + '</code></pre>');
5674
+ let tmpCodeText = tmpCodeLines.join('\n');
5675
+ let tmpHighlightedCode = this.highlightCode(tmpCodeText, tmpCodeLang);
5676
+ let tmpLineNumbersHTML = this.generateLineNumbers(tmpCodeText);
5677
+ tmpHTML.push('<div class="pict-content-code-wrap"><div class="pict-content-code-line-numbers">' + tmpLineNumbersHTML + '</div><pre><code class="language-' + this.escapeHTML(tmpCodeLang) + '">' + tmpHighlightedCode + '</code></pre></div>');
4973
5678
  }
4974
5679
  tmpInCodeBlock = false;
4975
5680
  tmpCodeFenceLength = 0;
@@ -4990,7 +5695,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
4990
5695
  tmpInList = false;
4991
5696
  }
4992
5697
  if (tmpInBlockquote) {
4993
- tmpHTML.push('<blockquote>' + this.parseMarkdown(tmpBlockquoteLines.join('\n'), pLinkResolver) + '</blockquote>');
5698
+ tmpHTML.push('<blockquote>' + this.parseMarkdown(tmpBlockquoteLines.join('\n'), pLinkResolver, pImageResolver) + '</blockquote>');
4994
5699
  tmpInBlockquote = false;
4995
5700
  tmpBlockquoteLines = [];
4996
5701
  }
@@ -5022,7 +5727,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5022
5727
  tmpBlockquoteLines.push(tmpLine.replace(/^>\s?/, ''));
5023
5728
  continue;
5024
5729
  } else if (tmpInBlockquote) {
5025
- tmpHTML.push('<blockquote>' + this.parseMarkdown(tmpBlockquoteLines.join('\n'), pLinkResolver) + '</blockquote>');
5730
+ tmpHTML.push('<blockquote>' + this.parseMarkdown(tmpBlockquoteLines.join('\n'), pLinkResolver, pImageResolver) + '</blockquote>');
5026
5731
  tmpInBlockquote = false;
5027
5732
  tmpBlockquoteLines = [];
5028
5733
  }
@@ -5047,7 +5752,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5047
5752
  tmpInList = false;
5048
5753
  }
5049
5754
  let tmpLevel = tmpHeadingMatch[1].length;
5050
- let tmpText = this.parseInline(tmpHeadingMatch[2], pLinkResolver);
5755
+ let tmpText = this.parseInline(tmpHeadingMatch[2], pLinkResolver, pImageResolver);
5051
5756
  let tmpID = tmpHeadingMatch[2].toLowerCase().replace(/[^\w\s-]/g, '').replace(/\s+/g, '-');
5052
5757
  tmpHTML.push('<h' + tmpLevel + ' id="' + tmpID + '">' + tmpText + '</h' + tmpLevel + '>');
5053
5758
  continue;
@@ -5065,7 +5770,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5065
5770
  tmpInList = true;
5066
5771
  tmpListType = 'ul';
5067
5772
  }
5068
- tmpHTML.push('<li>' + this.parseInline(tmpULMatch[2], pLinkResolver) + '</li>');
5773
+ tmpHTML.push('<li>' + this.parseInline(tmpULMatch[2], pLinkResolver, pImageResolver) + '</li>');
5069
5774
  continue;
5070
5775
  }
5071
5776
 
@@ -5081,7 +5786,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5081
5786
  tmpInList = true;
5082
5787
  tmpListType = 'ol';
5083
5788
  }
5084
- tmpHTML.push('<li>' + this.parseInline(tmpOLMatch[2], pLinkResolver) + '</li>');
5789
+ tmpHTML.push('<li>' + this.parseInline(tmpOLMatch[2], pLinkResolver, pImageResolver) + '</li>');
5085
5790
  continue;
5086
5791
  }
5087
5792
 
@@ -5113,7 +5818,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5113
5818
  });
5114
5819
  tmpTableHTML += '<thead><tr>';
5115
5820
  for (let h = 0; h < tmpHeaders.length; h++) {
5116
- tmpTableHTML += '<th>' + this.parseInline(tmpHeaders[h].trim(), pLinkResolver) + '</th>';
5821
+ tmpTableHTML += '<th>' + this.parseInline(tmpHeaders[h].trim(), pLinkResolver, pImageResolver) + '</th>';
5117
5822
  }
5118
5823
  tmpTableHTML += '</tr></thead>';
5119
5824
 
@@ -5129,7 +5834,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5129
5834
  });
5130
5835
  tmpTableHTML += '<tr>';
5131
5836
  for (let c = 0; c < tmpCells.length; c++) {
5132
- tmpTableHTML += '<td>' + this.parseInline(tmpCells[c].trim(), pLinkResolver) + '</td>';
5837
+ tmpTableHTML += '<td>' + this.parseInline(tmpCells[c].trim(), pLinkResolver, pImageResolver) + '</td>';
5133
5838
  }
5134
5839
  tmpTableHTML += '</tr>';
5135
5840
  }
@@ -5151,10 +5856,13 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5151
5856
  tmpHTML.push(tmpListType === 'ul' ? '</ul>' : '</ol>');
5152
5857
  }
5153
5858
  if (tmpInBlockquote) {
5154
- tmpHTML.push('<blockquote>' + this.parseMarkdown(tmpBlockquoteLines.join('\n'), pLinkResolver) + '</blockquote>');
5859
+ tmpHTML.push('<blockquote>' + this.parseMarkdown(tmpBlockquoteLines.join('\n'), pLinkResolver, pImageResolver) + '</blockquote>');
5155
5860
  }
5156
5861
  if (tmpInCodeBlock) {
5157
- tmpHTML.push('<pre><code>' + this.escapeHTML(tmpCodeLines.join('\n')) + '</code></pre>');
5862
+ let tmpCodeText = tmpCodeLines.join('\n');
5863
+ let tmpHighlightedCode = this.highlightCode(tmpCodeText, tmpCodeLang);
5864
+ let tmpLineNumbersHTML = this.generateLineNumbers(tmpCodeText);
5865
+ tmpHTML.push('<div class="pict-content-code-wrap"><div class="pict-content-code-line-numbers">' + tmpLineNumbersHTML + '</div><pre><code>' + tmpHighlightedCode + '</code></pre></div>');
5158
5866
  }
5159
5867
  return tmpHTML.join('\n');
5160
5868
  }
@@ -5164,9 +5872,10 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5164
5872
  *
5165
5873
  * @param {string} pText - The text to parse
5166
5874
  * @param {Function} [pLinkResolver] - Optional callback: (pHref, pLinkText) => { href, target, rel } or null
5875
+ * @param {Function} [pImageResolver] - Optional callback: (pSrc, pAlt) => resolvedSrc or null
5167
5876
  * @returns {string} HTML with inline elements
5168
5877
  */
5169
- parseInline(pText, pLinkResolver) {
5878
+ parseInline(pText, pLinkResolver, pImageResolver) {
5170
5879
  if (!pText) {
5171
5880
  return '';
5172
5881
  }
@@ -5187,7 +5896,16 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5187
5896
  tmpResult = tmpResult.replace(/\$([^\$\s])\$/g, '<span class="pict-content-katex-inline">$1</span>');
5188
5897
 
5189
5898
  // Images
5190
- tmpResult = tmpResult.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1">');
5899
+ tmpResult = tmpResult.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (pMatch, pAlt, pSrc) => {
5900
+ let tmpSrc = pSrc;
5901
+ if (typeof pImageResolver === 'function') {
5902
+ let tmpResolved = pImageResolver(pSrc, pAlt);
5903
+ if (tmpResolved) {
5904
+ tmpSrc = tmpResolved;
5905
+ }
5906
+ }
5907
+ return '<img src="' + tmpSrc + '" alt="' + pAlt + '">';
5908
+ });
5191
5909
 
5192
5910
  // Links
5193
5911
  tmpResult = tmpResult.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (pMatch, pLinkText, pHref) => {
@@ -5241,16 +5959,17 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5241
5959
  AutoInitializeOrdinal: 0
5242
5960
  };
5243
5961
  }, {
5244
- "pict-provider": 7
5962
+ "pict-provider": 7,
5963
+ "pict-section-code": 10
5245
5964
  }],
5246
- 10: [function (require, module, exports) {
5965
+ 13: [function (require, module, exports) {
5247
5966
  const libPictView = require('pict-view');
5248
5967
  const _ViewConfiguration = {
5249
5968
  ViewIdentifier: "Pict-Content",
5250
5969
  DefaultRenderable: "Pict-Content-Display",
5251
5970
  DefaultDestinationAddress: "#Pict-Content-Container",
5252
5971
  AutoRender: false,
5253
- CSS: /*css*/"\n\t\t.pict-content {\n\t\t\tpadding: 2em 3em;\n\t\t\tmax-width: 900px;\n\t\t\tmargin: 0 auto;\n\t\t}\n\t\t.pict-content-loading {\n\t\t\tdisplay: flex;\n\t\t\talign-items: center;\n\t\t\tjustify-content: center;\n\t\t\tmin-height: 200px;\n\t\t\tcolor: #8A7F72;\n\t\t\tfont-size: 1em;\n\t\t}\n\t\t.pict-content h1 {\n\t\t\tfont-size: 2em;\n\t\t\tcolor: #3D3229;\n\t\t\tborder-bottom: 1px solid #DDD6CA;\n\t\t\tpadding-bottom: 0.3em;\n\t\t\tmargin-top: 0;\n\t\t}\n\t\t.pict-content h2 {\n\t\t\tfont-size: 1.5em;\n\t\t\tcolor: #3D3229;\n\t\t\tborder-bottom: 1px solid #EAE3D8;\n\t\t\tpadding-bottom: 0.25em;\n\t\t\tmargin-top: 1.5em;\n\t\t}\n\t\t.pict-content h3 {\n\t\t\tfont-size: 1.25em;\n\t\t\tcolor: #3D3229;\n\t\t\tmargin-top: 1.25em;\n\t\t}\n\t\t.pict-content h4, .pict-content h5, .pict-content h6 {\n\t\t\tcolor: #5E5549;\n\t\t\tmargin-top: 1em;\n\t\t}\n\t\t.pict-content p {\n\t\t\tline-height: 1.7;\n\t\t\tcolor: #423D37;\n\t\t\tmargin: 0.75em 0;\n\t\t}\n\t\t.pict-content a {\n\t\t\tcolor: #2E7D74;\n\t\t\ttext-decoration: none;\n\t\t}\n\t\t.pict-content a:hover {\n\t\t\ttext-decoration: underline;\n\t\t}\n\t\t.pict-content pre {\n\t\t\tbackground: #3D3229;\n\t\t\tcolor: #E8E0D4;\n\t\t\tpadding: 1.25em;\n\t\t\tborder-radius: 6px;\n\t\t\toverflow-x: auto;\n\t\t\tline-height: 1.5;\n\t\t\tfont-size: 0.9em;\n\t\t}\n\t\t.pict-content code {\n\t\t\tbackground: #F0ECE4;\n\t\t\tpadding: 0.15em 0.4em;\n\t\t\tborder-radius: 3px;\n\t\t\tfont-size: 0.9em;\n\t\t\tcolor: #9E6B47;\n\t\t}\n\t\t.pict-content pre code {\n\t\t\tbackground: none;\n\t\t\tpadding: 0;\n\t\t\tcolor: inherit;\n\t\t\tfont-size: inherit;\n\t\t}\n\t\t.pict-content blockquote {\n\t\t\tborder-left: 4px solid #2E7D74;\n\t\t\tmargin: 1em 0;\n\t\t\tpadding: 0.5em 1em;\n\t\t\tbackground: #F7F5F0;\n\t\t\tcolor: #5E5549;\n\t\t}\n\t\t.pict-content blockquote p {\n\t\t\tmargin: 0.25em 0;\n\t\t}\n\t\t.pict-content ul, .pict-content ol {\n\t\t\tpadding-left: 2em;\n\t\t\tline-height: 1.8;\n\t\t}\n\t\t.pict-content li {\n\t\t\tmargin: 0.25em 0;\n\t\t\tcolor: #423D37;\n\t\t}\n\t\t.pict-content hr {\n\t\t\tborder: none;\n\t\t\tborder-top: 1px solid #DDD6CA;\n\t\t\tmargin: 2em 0;\n\t\t}\n\t\t.pict-content table {\n\t\t\twidth: 100%;\n\t\t\tborder-collapse: collapse;\n\t\t\tmargin: 1em 0;\n\t\t}\n\t\t.pict-content table th {\n\t\t\tbackground: #F5F0E8;\n\t\t\tborder: 1px solid #DDD6CA;\n\t\t\tpadding: 0.6em 0.8em;\n\t\t\ttext-align: left;\n\t\t\tfont-weight: 600;\n\t\t\tcolor: #3D3229;\n\t\t}\n\t\t.pict-content table td {\n\t\t\tborder: 1px solid #DDD6CA;\n\t\t\tpadding: 0.5em 0.8em;\n\t\t\tcolor: #423D37;\n\t\t}\n\t\t.pict-content table tr:nth-child(even) {\n\t\t\tbackground: #F7F5F0;\n\t\t}\n\t\t.pict-content img {\n\t\t\tmax-width: 100%;\n\t\t\theight: auto;\n\t\t}\n\t\t.pict-content pre.mermaid {\n\t\t\tbackground: #fff;\n\t\t\tcolor: #3D3229;\n\t\t\ttext-align: center;\n\t\t\tpadding: 1em;\n\t\t}\n\t\t.pict-content .pict-content-katex-display {\n\t\t\ttext-align: center;\n\t\t\tmargin: 1em 0;\n\t\t\tpadding: 0.5em;\n\t\t\toverflow-x: auto;\n\t\t}\n\t\t.pict-content .pict-content-katex-inline {\n\t\t\tdisplay: inline;\n\t\t}\n\t",
5972
+ CSS: /*css*/"\n\t\t.pict-content {\n\t\t\tpadding: 2em 3em;\n\t\t\tmax-width: 900px;\n\t\t\tmargin: 0 auto;\n\t\t}\n\t\t.pict-content-loading {\n\t\t\tdisplay: flex;\n\t\t\talign-items: center;\n\t\t\tjustify-content: center;\n\t\t\tmin-height: 200px;\n\t\t\tcolor: #8A7F72;\n\t\t\tfont-size: 1em;\n\t\t}\n\t\t.pict-content h1 {\n\t\t\tfont-size: 2em;\n\t\t\tcolor: #3D3229;\n\t\t\tborder-bottom: 1px solid #DDD6CA;\n\t\t\tpadding-bottom: 0.3em;\n\t\t\tmargin-top: 0;\n\t\t}\n\t\t.pict-content h2 {\n\t\t\tfont-size: 1.5em;\n\t\t\tcolor: #3D3229;\n\t\t\tborder-bottom: 1px solid #EAE3D8;\n\t\t\tpadding-bottom: 0.25em;\n\t\t\tmargin-top: 1.5em;\n\t\t}\n\t\t.pict-content h3 {\n\t\t\tfont-size: 1.25em;\n\t\t\tcolor: #3D3229;\n\t\t\tmargin-top: 1.25em;\n\t\t}\n\t\t.pict-content h4, .pict-content h5, .pict-content h6 {\n\t\t\tcolor: #5E5549;\n\t\t\tmargin-top: 1em;\n\t\t}\n\t\t.pict-content p {\n\t\t\tline-height: 1.7;\n\t\t\tcolor: #423D37;\n\t\t\tmargin: 0.75em 0;\n\t\t}\n\t\t.pict-content a {\n\t\t\tcolor: #2E7D74;\n\t\t\ttext-decoration: none;\n\t\t}\n\t\t.pict-content a:hover {\n\t\t\ttext-decoration: underline;\n\t\t}\n\t\t.pict-content-code-wrap {\n\t\t\tposition: relative;\n\t\t\tfont-family: 'SFMono-Regular', 'SF Mono', 'Menlo', 'Consolas', 'Liberation Mono', 'Courier New', monospace;\n\t\t\tfont-size: 14px;\n\t\t\tline-height: 1.5;\n\t\t\tborder-radius: 6px;\n\t\t\toverflow: auto;\n\t\t\tmargin: 1em 0;\n\t\t\tbackground: #3D3229;\n\t\t}\n\t\t.pict-content-code-wrap .pict-content-code-line-numbers {\n\t\t\tposition: absolute;\n\t\t\ttop: 0;\n\t\t\tleft: 0;\n\t\t\twidth: 40px;\n\t\t\tpadding: 1.25em 0;\n\t\t\ttext-align: right;\n\t\t\tbackground: #342A22;\n\t\t\tborder-right: 1px solid #4A3F35;\n\t\t\tcolor: #8A7F72;\n\t\t\tfont-size: 13px;\n\t\t\tline-height: 1.5;\n\t\t\tuser-select: none;\n\t\t\tpointer-events: none;\n\t\t\tbox-sizing: border-box;\n\t\t}\n\t\t.pict-content-code-wrap .pict-content-code-line-numbers span {\n\t\t\tdisplay: block;\n\t\t\tpadding: 0 8px 0 0;\n\t\t}\n\t\t.pict-content-code-wrap pre {\n\t\t\tmargin: 0;\n\t\t\tbackground: #3D3229;\n\t\t\tcolor: #E8E0D4;\n\t\t\tpadding: 1.25em 1.25em 1.25em 52px;\n\t\t\tborder-radius: 6px;\n\t\t\toverflow-x: auto;\n\t\t\tline-height: 1.5;\n\t\t\tfont-size: inherit;\n\t\t}\n\t\t.pict-content-code-wrap pre code {\n\t\t\tbackground: none;\n\t\t\tpadding: 0;\n\t\t\tcolor: inherit;\n\t\t\tfont-size: inherit;\n\t\t\tfont-family: inherit;\n\t\t}\n\t\t.pict-content-code-wrap .keyword { color: #C678DD; }\n\t\t.pict-content-code-wrap .string { color: #98C379; }\n\t\t.pict-content-code-wrap .number { color: #D19A66; }\n\t\t.pict-content-code-wrap .comment { color: #7F848E; font-style: italic; }\n\t\t.pict-content-code-wrap .operator { color: #56B6C2; }\n\t\t.pict-content-code-wrap .punctuation { color: #E8E0D4; }\n\t\t.pict-content-code-wrap .function-name { color: #61AFEF; }\n\t\t.pict-content-code-wrap .property { color: #E06C75; }\n\t\t.pict-content-code-wrap .tag { color: #E06C75; }\n\t\t.pict-content-code-wrap .attr-name { color: #D19A66; }\n\t\t.pict-content-code-wrap .attr-value { color: #98C379; }\n\t\t.pict-content pre {\n\t\t\tbackground: #3D3229;\n\t\t\tcolor: #E8E0D4;\n\t\t\tpadding: 1.25em;\n\t\t\tborder-radius: 6px;\n\t\t\toverflow-x: auto;\n\t\t\tline-height: 1.5;\n\t\t\tfont-size: 0.9em;\n\t\t}\n\t\t.pict-content code {\n\t\t\tbackground: #F0ECE4;\n\t\t\tpadding: 0.15em 0.4em;\n\t\t\tborder-radius: 3px;\n\t\t\tfont-size: 0.9em;\n\t\t\tcolor: #9E6B47;\n\t\t}\n\t\t.pict-content pre code {\n\t\t\tbackground: none;\n\t\t\tpadding: 0;\n\t\t\tcolor: inherit;\n\t\t\tfont-size: inherit;\n\t\t}\n\t\t.pict-content blockquote {\n\t\t\tborder-left: 4px solid #2E7D74;\n\t\t\tmargin: 1em 0;\n\t\t\tpadding: 0.5em 1em;\n\t\t\tbackground: #F7F5F0;\n\t\t\tcolor: #5E5549;\n\t\t}\n\t\t.pict-content blockquote p {\n\t\t\tmargin: 0.25em 0;\n\t\t}\n\t\t.pict-content ul, .pict-content ol {\n\t\t\tpadding-left: 2em;\n\t\t\tline-height: 1.8;\n\t\t}\n\t\t.pict-content li {\n\t\t\tmargin: 0.25em 0;\n\t\t\tcolor: #423D37;\n\t\t}\n\t\t.pict-content hr {\n\t\t\tborder: none;\n\t\t\tborder-top: 1px solid #DDD6CA;\n\t\t\tmargin: 2em 0;\n\t\t}\n\t\t.pict-content table {\n\t\t\twidth: 100%;\n\t\t\tborder-collapse: collapse;\n\t\t\tmargin: 1em 0;\n\t\t}\n\t\t.pict-content table th {\n\t\t\tbackground: #F5F0E8;\n\t\t\tborder: 1px solid #DDD6CA;\n\t\t\tpadding: 0.6em 0.8em;\n\t\t\ttext-align: left;\n\t\t\tfont-weight: 600;\n\t\t\tcolor: #3D3229;\n\t\t}\n\t\t.pict-content table td {\n\t\t\tborder: 1px solid #DDD6CA;\n\t\t\tpadding: 0.5em 0.8em;\n\t\t\tcolor: #423D37;\n\t\t}\n\t\t.pict-content table tr:nth-child(even) {\n\t\t\tbackground: #F7F5F0;\n\t\t}\n\t\t.pict-content img {\n\t\t\tmax-width: 100%;\n\t\t\theight: auto;\n\t\t}\n\t\t.pict-content pre.mermaid {\n\t\t\tbackground: #fff;\n\t\t\tcolor: #3D3229;\n\t\t\ttext-align: center;\n\t\t\tpadding: 1em;\n\t\t}\n\t\t.pict-content .pict-content-katex-display {\n\t\t\ttext-align: center;\n\t\t\tmargin: 1em 0;\n\t\t\tpadding: 0.5em;\n\t\t\toverflow-x: auto;\n\t\t}\n\t\t.pict-content .pict-content-katex-inline {\n\t\t\tdisplay: inline;\n\t\t}\n\t",
5254
5973
  Templates: [{
5255
5974
  Hash: "Pict-Content-Template",
5256
5975
  Template: /*html*/"\n<div class=\"pict-content\" id=\"Pict-Content-Body\">\n\t<div class=\"pict-content-loading\">Loading content...</div>\n</div>\n"
@@ -5379,19 +6098,19 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5379
6098
  module.exports = PictContentView;
5380
6099
  module.exports.default_configuration = _ViewConfiguration;
5381
6100
  }, {
5382
- "pict-view": 12
6101
+ "pict-view": 15
5383
6102
  }],
5384
- 11: [function (require, module, exports) {
6103
+ 14: [function (require, module, exports) {
5385
6104
  module.exports = {
5386
6105
  "name": "pict-view",
5387
- "version": "1.0.66",
6106
+ "version": "1.0.67",
5388
6107
  "description": "Pict View Base Class",
5389
6108
  "main": "source/Pict-View.js",
5390
6109
  "scripts": {
5391
- "test": "mocha -u tdd -R spec",
5392
- "tests": "mocha -u tdd -R spec -g",
6110
+ "test": "npx quack test",
6111
+ "tests": "npx quack test -g",
5393
6112
  "start": "node source/Pict-View.js",
5394
- "coverage": "nyc --reporter=lcov --reporter=text-lcov npm test",
6113
+ "coverage": "npx quack coverage",
5395
6114
  "build": "npx quack build",
5396
6115
  "docker-dev-build": "docker build ./ -f Dockerfile_LUXURYCode -t pict-view-image:local",
5397
6116
  "docker-dev-run": "docker run -it -d --name pict-view-dev -p 30001:8080 -p 38086:8086 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/pict-view\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" pict-view-image:local",
@@ -5415,7 +6134,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5415
6134
  "browser-env": "^3.3.0",
5416
6135
  "eslint": "^9.39.1",
5417
6136
  "pict": "^1.0.348",
5418
- "quackage": "^1.0.51",
6137
+ "quackage": "^1.0.58",
5419
6138
  "typescript": "^5.9.3"
5420
6139
  },
5421
6140
  "mocha": {
@@ -5430,12 +6149,12 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5430
6149
  "watch-ignore": ["lib/vendor"]
5431
6150
  },
5432
6151
  "dependencies": {
5433
- "fable": "^3.1.57",
5434
- "fable-serviceproviderbase": "^3.0.18"
6152
+ "fable": "^3.1.63",
6153
+ "fable-serviceproviderbase": "^3.0.19"
5435
6154
  }
5436
6155
  };
5437
6156
  }, {}],
5438
- 12: [function (require, module, exports) {
6157
+ 15: [function (require, module, exports) {
5439
6158
  const libFableServiceBase = require('fable-serviceproviderbase');
5440
6159
  const libPackage = require('../package.json');
5441
6160
  const defaultPictViewSettings = {
@@ -6599,10 +7318,10 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
6599
7318
  }
6600
7319
  module.exports = PictView;
6601
7320
  }, {
6602
- "../package.json": 11,
7321
+ "../package.json": 14,
6603
7322
  "fable-serviceproviderbase": 2
6604
7323
  }],
6605
- 13: [function (require, module, exports) {
7324
+ 16: [function (require, module, exports) {
6606
7325
  module.exports = {
6607
7326
  "Name": "Pict Docuserve",
6608
7327
  "Hash": "Docuserve",
@@ -6615,7 +7334,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
6615
7334
  }
6616
7335
  };
6617
7336
  }, {}],
6618
- 14: [function (require, module, exports) {
7337
+ 17: [function (require, module, exports) {
6619
7338
  const libPictApplication = require('pict-application');
6620
7339
 
6621
7340
  // Provider
@@ -6672,7 +7391,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
6672
7391
  // Load the catalog, then render the layout
6673
7392
  let tmpDocProvider = this.pict.providers['Docuserve-Documentation'];
6674
7393
  tmpDocProvider.loadCatalog(() => {
6675
- // Set the page title from cover.md or _topbar.md
7394
+ // Set the page title from _cover.md or _topbar.md
6676
7395
  let tmpDocuserve = this.pict.AppData.Docuserve;
6677
7396
  if (tmpDocuserve.CoverLoaded && tmpDocuserve.Cover && tmpDocuserve.Cover.Title) {
6678
7397
  document.title = tmpDocuserve.Cover.Title.replace(/<[^>]*>/g, '');
@@ -6880,17 +7599,17 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
6880
7599
  module.exports = DocuserveApplication;
6881
7600
  module.exports.default_configuration = require('./Pict-Application-Docuserve-Configuration.json');
6882
7601
  }, {
6883
- "./Pict-Application-Docuserve-Configuration.json": 13,
6884
- "./providers/Pict-Provider-Docuserve-Documentation.js": 15,
6885
- "./views/PictView-Docuserve-Content.js": 16,
6886
- "./views/PictView-Docuserve-Layout.js": 17,
6887
- "./views/PictView-Docuserve-Search.js": 18,
6888
- "./views/PictView-Docuserve-Sidebar.js": 19,
6889
- "./views/PictView-Docuserve-Splash.js": 20,
6890
- "./views/PictView-Docuserve-TopBar.js": 21,
7602
+ "./Pict-Application-Docuserve-Configuration.json": 16,
7603
+ "./providers/Pict-Provider-Docuserve-Documentation.js": 18,
7604
+ "./views/PictView-Docuserve-Content.js": 19,
7605
+ "./views/PictView-Docuserve-Layout.js": 20,
7606
+ "./views/PictView-Docuserve-Search.js": 21,
7607
+ "./views/PictView-Docuserve-Sidebar.js": 22,
7608
+ "./views/PictView-Docuserve-Splash.js": 23,
7609
+ "./views/PictView-Docuserve-TopBar.js": 24,
6891
7610
  "pict-application": 5
6892
7611
  }],
6893
- 15: [function (require, module, exports) {
7612
+ 18: [function (require, module, exports) {
6894
7613
  const libPictProvider = require('pict-provider');
6895
7614
  const libLunr = require('lunr');
6896
7615
  const libPictSectionContent = require('pict-section-content');
@@ -6947,10 +7666,40 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
6947
7666
  }
6948
7667
 
6949
7668
  /**
6950
- * Load all documentation data sources: catalog, cover.md, _sidebar.md.
7669
+ * Create an image resolver closure for the content provider.
7670
+ *
7671
+ * Resolves relative image URLs against the directory of the document
7672
+ * being rendered, so that images referenced with relative paths in
7673
+ * markdown (e.g. `![graph](diagram.svg)`) resolve correctly even
7674
+ * when the page uses hash-based routing.
7675
+ *
7676
+ * @param {string} pDocURL - The URL the markdown document was fetched from
7677
+ * @returns {Function} An image resolver callback: (pSrc, pAlt) => resolvedSrc
7678
+ */
7679
+ _createImageResolver(pDocURL) {
7680
+ // Extract the directory portion of the document URL
7681
+ let tmpBaseDir = '';
7682
+ if (pDocURL) {
7683
+ let tmpLastSlash = pDocURL.lastIndexOf('/');
7684
+ if (tmpLastSlash >= 0) {
7685
+ tmpBaseDir = pDocURL.substring(0, tmpLastSlash + 1);
7686
+ }
7687
+ }
7688
+ return (pSrc, pAlt) => {
7689
+ // Leave absolute URLs, data URIs, and root-relative paths unchanged
7690
+ if (pSrc.match(/^https?:\/\//) || pSrc.match(/^data:/) || pSrc.match(/^\//)) {
7691
+ return pSrc;
7692
+ }
7693
+ // Prepend the document's directory to make relative paths work
7694
+ return tmpBaseDir + pSrc;
7695
+ };
7696
+ }
7697
+
7698
+ /**
7699
+ * Load all documentation data sources: catalog, _cover.md, _sidebar.md.
6951
7700
  *
6952
7701
  * Loads the catalog first (it provides the fallback data), then attempts
6953
- * to load cover.md and _sidebar.md in parallel. If those markdown files
7702
+ * to load _cover.md and _sidebar.md in parallel. If those markdown files
6954
7703
  * exist they drive the splash and sidebar views; otherwise the catalog
6955
7704
  * data is used as a fallback.
6956
7705
  *
@@ -6960,7 +7709,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
6960
7709
  let tmpCallback = typeof fCallback === 'function' ? fCallback : () => {};
6961
7710
  let tmpCatalogURL = this.pict.AppData.Docuserve.CatalogURL || 'retold-catalog.json';
6962
7711
  let tmpLoadOptionalFiles = () => {
6963
- // Load cover.md, _sidebar.md, _topbar.md, errorpage.md and keyword index in parallel.
7712
+ // Load _cover.md, _sidebar.md, _topbar.md, errorpage.md and keyword index in parallel.
6964
7713
  // When all are done, if we still have no sidebar data, try to auto-discover
6965
7714
  // a README.md so the site works with plain markdown folders.
6966
7715
  let tmpPending = 5;
@@ -7060,9 +7809,9 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
7060
7809
  }
7061
7810
 
7062
7811
  /**
7063
- * Fetch and parse cover.md into structured data for the splash view.
7812
+ * Fetch and parse _cover.md into structured data for the splash view.
7064
7813
  *
7065
- * The expected cover.md format follows the docsify convention:
7814
+ * The expected _cover.md format follows the docsify convention:
7066
7815
  * # Title
7067
7816
  * > Tagline
7068
7817
  * Description paragraph text.
@@ -7077,29 +7826,29 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
7077
7826
  loadCover(fCallback) {
7078
7827
  let tmpCallback = typeof fCallback === 'function' ? fCallback : () => {};
7079
7828
  let tmpDocsBase = this.pict.AppData.Docuserve.DocsBaseURL || '';
7080
- fetch(tmpDocsBase + 'cover.md').then(pResponse => {
7829
+ fetch(tmpDocsBase + '_cover.md').then(pResponse => {
7081
7830
  if (!pResponse.ok) {
7082
7831
  return null;
7083
7832
  }
7084
7833
  return pResponse.text();
7085
7834
  }).then(pMarkdown => {
7086
7835
  if (!pMarkdown) {
7087
- this.log.info('Docuserve: No cover.md found; splash will use catalog data.');
7836
+ this.log.info('Docuserve: No _cover.md found; splash will use catalog data.');
7088
7837
  return tmpCallback();
7089
7838
  }
7090
7839
  this.pict.AppData.Docuserve.Cover = this.parseCover(pMarkdown);
7091
7840
  this.pict.AppData.Docuserve.CoverLoaded = true;
7092
7841
  return tmpCallback();
7093
7842
  }).catch(pError => {
7094
- this.log.warn("Docuserve: Error loading cover.md: ".concat(pError));
7843
+ this.log.warn("Docuserve: Error loading _cover.md: ".concat(pError));
7095
7844
  return tmpCallback();
7096
7845
  });
7097
7846
  }
7098
7847
 
7099
7848
  /**
7100
- * Parse cover.md markdown text into a structured object.
7849
+ * Parse _cover.md markdown text into a structured object.
7101
7850
  *
7102
- * @param {string} pMarkdown - Raw cover.md content
7851
+ * @param {string} pMarkdown - Raw _cover.md content
7103
7852
  * @returns {Object} Parsed cover data
7104
7853
  */
7105
7854
  parseCover(pMarkdown) {
@@ -7913,7 +8662,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
7913
8662
  if (!pMarkdown) {
7914
8663
  return tmpCallback('Document not found', this.getErrorPageHTML(pURL));
7915
8664
  }
7916
- let tmpHTML = this._ContentProvider.parseMarkdown(pMarkdown, this._createLinkResolver(pCurrentGroup, pCurrentModule, pCurrentDocPath));
8665
+ let tmpHTML = this._ContentProvider.parseMarkdown(pMarkdown, this._createLinkResolver(pCurrentGroup, pCurrentModule, pCurrentDocPath), this._createImageResolver(pURL));
7917
8666
  this._ContentCache[pURL] = tmpHTML;
7918
8667
  return tmpCallback(null, tmpHTML);
7919
8668
  }).catch(pError => {
@@ -7997,9 +8746,9 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
7997
8746
  }, {
7998
8747
  "lunr": 3,
7999
8748
  "pict-provider": 7,
8000
- "pict-section-content": 8
8749
+ "pict-section-content": 11
8001
8750
  }],
8002
- 16: [function (require, module, exports) {
8751
+ 19: [function (require, module, exports) {
8003
8752
  const libPictContentView = require('pict-section-content');
8004
8753
  const _ViewConfiguration = {
8005
8754
  ViewIdentifier: "Docuserve-Content",
@@ -8062,9 +8811,9 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
8062
8811
  module.exports = DocuserveContentView;
8063
8812
  module.exports.default_configuration = _ViewConfiguration;
8064
8813
  }, {
8065
- "pict-section-content": 8
8814
+ "pict-section-content": 11
8066
8815
  }],
8067
- 17: [function (require, module, exports) {
8816
+ 20: [function (require, module, exports) {
8068
8817
  const libPictView = require('pict-view');
8069
8818
  const _ViewConfiguration = {
8070
8819
  ViewIdentifier: "Docuserve-Layout",
@@ -8117,9 +8866,9 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
8117
8866
  module.exports = DocuserveLayoutView;
8118
8867
  module.exports.default_configuration = _ViewConfiguration;
8119
8868
  }, {
8120
- "pict-view": 12
8869
+ "pict-view": 15
8121
8870
  }],
8122
- 18: [function (require, module, exports) {
8871
+ 21: [function (require, module, exports) {
8123
8872
  const libPictView = require('pict-view');
8124
8873
  const _ViewConfiguration = {
8125
8874
  ViewIdentifier: "Docuserve-Search",
@@ -8247,9 +8996,9 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
8247
8996
  module.exports = DocuserveSearchView;
8248
8997
  module.exports.default_configuration = _ViewConfiguration;
8249
8998
  }, {
8250
- "pict-view": 12
8999
+ "pict-view": 15
8251
9000
  }],
8252
- 19: [function (require, module, exports) {
9001
+ 22: [function (require, module, exports) {
8253
9002
  const libPictView = require('pict-view');
8254
9003
  const _ViewConfiguration = {
8255
9004
  ViewIdentifier: "Docuserve-Sidebar",
@@ -8470,9 +9219,9 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
8470
9219
  module.exports = DocusserveSidebarView;
8471
9220
  module.exports.default_configuration = _ViewConfiguration;
8472
9221
  }, {
8473
- "pict-view": 12
9222
+ "pict-view": 15
8474
9223
  }],
8475
- 20: [function (require, module, exports) {
9224
+ 23: [function (require, module, exports) {
8476
9225
  const libPictView = require('pict-view');
8477
9226
  const _ViewConfiguration = {
8478
9227
  ViewIdentifier: "Docuserve-Splash",
@@ -8506,7 +9255,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
8506
9255
  }
8507
9256
 
8508
9257
  /**
8509
- * Render the splash screen from parsed cover.md data.
9258
+ * Render the splash screen from parsed _cover.md data.
8510
9259
  *
8511
9260
  * @param {Object} pCover - The parsed cover data { Title, Tagline, Description, Highlights, Actions }
8512
9261
  */
@@ -8549,7 +9298,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
8549
9298
  }
8550
9299
 
8551
9300
  /**
8552
- * Render the splash screen from catalog data as a fallback when cover.md
9301
+ * Render the splash screen from catalog data as a fallback when _cover.md
8553
9302
  * is not available.
8554
9303
  *
8555
9304
  * @param {Object} pDocuserve - The AppData.Docuserve state
@@ -8624,9 +9373,9 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
8624
9373
  module.exports = DocusserveSplashView;
8625
9374
  module.exports.default_configuration = _ViewConfiguration;
8626
9375
  }, {
8627
- "pict-view": 12
9376
+ "pict-view": 15
8628
9377
  }],
8629
- 21: [function (require, module, exports) {
9378
+ 24: [function (require, module, exports) {
8630
9379
  const libPictView = require('pict-view');
8631
9380
  const _ViewConfiguration = {
8632
9381
  ViewIdentifier: "Docuserve-TopBar",
@@ -8727,8 +9476,8 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
8727
9476
  module.exports = DocuserveTopBarView;
8728
9477
  module.exports.default_configuration = _ViewConfiguration;
8729
9478
  }, {
8730
- "pict-view": 12
9479
+ "pict-view": 15
8731
9480
  }]
8732
- }, {}, [14])(14);
9481
+ }, {}, [17])(17);
8733
9482
  });
8734
9483
  //# sourceMappingURL=pict-docuserve.js.map