diff --git a/.gitignore b/.gitignore index d94ea37..07d260c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,9 @@ _site _site/** _site/*.* node_modules +api-json +api-raw +dist # excluding IG assemblies and xml files src/*.dll diff --git a/IgniteUI.Blazor.GridLite.filterConfig.yml b/IgniteUI.Blazor.GridLite.filterConfig.yml new file mode 100644 index 0000000..a7df800 --- /dev/null +++ b/IgniteUI.Blazor.GridLite.filterConfig.yml @@ -0,0 +1,16 @@ +apiRules: +- exclude: + uidRegex: ^IgniteUI\.Blazor\.Controls\._Imports$ + type: Class +- exclude: + uidRegex: ^\< + type: Class +- exclude: + hasAttribute: + uid: System.Runtime.CompilerServices.CompilerGeneratedAttribute +- include: + uidRegex: ^IgniteUI\.Blazor + type: Namespace +- exclude: + uidRegex: . + type: Namespace diff --git a/IgniteUI.Blazor.filterConfig.yml b/IgniteUI.Blazor.filterConfig.yml new file mode 100644 index 0000000..576444a --- /dev/null +++ b/IgniteUI.Blazor.filterConfig.yml @@ -0,0 +1,10 @@ +apiRules: +- exclude: + uidRegex: ^IgniteUI\.Blazor\._Imports$ + type: Class +- exclude: + uidRegex: ^IgniteUI\.Blazor\.Controls\.Description + type: Namespace +- exclude: + uidRegex: ^System\.Runtime\.CompilerServices\. + type: Class \ No newline at end of file diff --git a/api-templates/ManagedReference.json.primary.js b/api-templates/ManagedReference.json.primary.js new file mode 100644 index 0000000..be3cca9 --- /dev/null +++ b/api-templates/ManagedReference.json.primary.js @@ -0,0 +1,14 @@ +exports.transform = function (model) { + if (model && model.inheritedMembers) { + model.inheritedMembers.forEach(function (member) { + if (member.uid) { + // Strip method parameters (everything from first '(') before finding the class name + var parenIndex = member.uid.indexOf('('); + var uidWithoutParams = parenIndex > 0 ? member.uid.substring(0, parenIndex) : member.uid; + var lastDot = uidWithoutParams.lastIndexOf('.'); + member.inheritedFromClass = lastDot > 0 ? uidWithoutParams.substring(0, lastDot) : uidWithoutParams; + } + }); + } + return model; +}; diff --git a/api-templates/ManagedReference.json.primary.tmpl b/api-templates/ManagedReference.json.primary.tmpl new file mode 100644 index 0000000..fc64301 --- /dev/null +++ b/api-templates/ManagedReference.json.primary.tmpl @@ -0,0 +1,133 @@ +{ + "uid": "{{uid}}", + "id": 0, + "name": "{{name.0.value}}", + "fullName": "{{fullName.0.value}}", + "namespace": "{{namespace.uid}}", + "kindString": "{{type}}", + "comment": { + "summary": [ + { + "kindString": "text", + "text": "{{summary}}" + }, + { + "kindString": "code", + "text": "{{syntax.content.0.value}}" + } + ] + }, + "inheritance": [ + {{#if inheritance}} + {{#each inheritance}} + { + "uid": "{{uid}}", + "id": 0, + "name": "{{name.0.value}}" + }{{#unless @last}},{{/unless}} + {{/each}} + {{/if}} + ], + "implements": [ + {{#if implements}} + {{#each implements}} + { + "uid": "{{uid}}", + "id": 0, + "name": "{{name.0.value}}" + }{{#unless @last}},{{/unless}} + {{/each}} + {{/if}} + ], + "children": [ + {{#if inheritedMembers}} + {{#each inheritedMembers}} + { + "uid": "{{uid}}", + "id": 0, + "name": "{{name.0.value}}", + "fullName": "{{fullName.0.value}}", + "kindString": "{{type}}", + "inheritedFrom": "{{inheritedFromClass}}", + "comment": { + "summary": [ + { + "kindString": "text", + "text": "{{summary}}" + }, + { + "kindString": "code", + "text": "{{syntax.content.0.value}}" + } + ] + }, + {{#if syntax}} + "syntax": { + "parameters": [ + {{#if syntax.parameters}} + {{#each syntax.parameters}} + { + "name": "{{id}}", + "type": "{{type.name.0.value}}", + "fullTypeName": "{{type.fullName.0.value}}" + }{{#unless @last}},{{/unless}} + {{/each}} + {{/if}} + ], + "return": { + {{#if syntax.return}} + "type": "{{syntax.return.type.name.0.value}}", + "fullTypeName": "{{syntax.return.type.fullName.0.value}}" + {{/if}} + } + } + {{/if}} + }{{#unless @last}},{{/unless}} + {{/each}} + {{/if}} + {{#if children}} + {{#each children}} + { + "uid": "{{uid}}", + "id": 0, + "name": "{{name.0.value}}", + "fullName": "{{fullName.0.value}}", + "kindString": "{{type}}", + "comment": { + "summary": [ + { + "kindString": "text", + "text": "{{summary}}" + }, + { + "kindString": "code", + "text": "{{syntax.content.0.value}}" + } + ] + }, + {{#if syntax}} + "syntax": { + "parameters": [ + {{#if syntax.parameters}} + {{#each syntax.parameters}} + { + "name": "{{id}}", + "type": "{{type.name.0.value}}", + "fullTypeName": "{{type.fullName.0.value}}" + }{{#unless @last}},{{/unless}} + {{/each}} + {{/if}} + ], + "return": { + {{#if syntax.return}} + "type": "{{syntax.return.type.name.0.value}}", + "fullTypeName": "{{syntax.return.type.fullName.0.value}}" + {{/if}} + } + } + {{/if}} + }{{#unless @last}},{{/unless}} + {{/each}} + {{/if}} + ] +} \ No newline at end of file diff --git a/api-templates/Toc.json.primary.tmpl b/api-templates/Toc.json.primary.tmpl new file mode 100644 index 0000000..d518628 --- /dev/null +++ b/api-templates/Toc.json.primary.tmpl @@ -0,0 +1,13 @@ +{ +"name": "{{_assemblyName}}", +"children": [ + {{#each items}} + { + "uid": "{{topicUid}}", + "name": "{{name}}", + "href": "{{topicHref}}", + "kindString": "{{type}}" + }{{#unless @last}},{{/unless}} + {{/each}} +] +} \ No newline at end of file diff --git a/app/blazor-app.csproj b/app/blazor-app.csproj index 6ef97fd..57e3af8 100644 --- a/app/blazor-app.csproj +++ b/app/blazor-app.csproj @@ -1,32 +1,54 @@ - + net6.0 enable enable - true + true + + + + + + + $(PkgIgniteUI_Blazor_Lite)\lib\net8.0\IgniteUI.Blazor.Lite.dll + true + + + $(PkgIgniteUI_Blazor_GridLite)\lib\net8.0\IgniteUI.Blazor.GridLite.dll + true + + + + + - - IgniteUI.Blazor.xml - Always - - - IgniteUI.Blazor.Documents.Core.xml - Always - - - IgniteUI.Blazor.Documents.Excel.xml - Always - + + + + + + IgniteUI.Blazor.xml + Always + + + IgniteUI.Blazor.Documents.Core.xml + Always + + + IgniteUI.Blazor.Documents.Excel.xml + Always + + diff --git a/docfx-build-IgniteUI.Blazor.Documents.Core.json b/docfx-build-IgniteUI.Blazor.Documents.Core.json new file mode 100644 index 0000000..5a1479a --- /dev/null +++ b/docfx-build-IgniteUI.Blazor.Documents.Core.json @@ -0,0 +1,30 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ + "src/IgniteUI.Blazor.Documents.Core.dll" + ] + } + ], + "dest": "api" + } + ], + "build": { + "template": ["api-templates"], + "globalMetadata": { + "_assemblyName": "IgniteUI.Blazor.Documents.Core" + }, + "content": [ + { + "files": [ + "api/**.yml", + "api/toc.yml" + ] + } + ], + "rawModelOutputFolder": "api-raw", + "dest": "api-json" + } +} \ No newline at end of file diff --git a/docfx-build-IgniteUI.Blazor.Documents.Excel.json b/docfx-build-IgniteUI.Blazor.Documents.Excel.json new file mode 100644 index 0000000..02dc277 --- /dev/null +++ b/docfx-build-IgniteUI.Blazor.Documents.Excel.json @@ -0,0 +1,30 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ + "src/IgniteUI.Blazor.Documents.Excel.dll" + ] + } + ], + "dest": "api" + } + ], + "build": { + "template": ["api-templates"], + "globalMetadata": { + "_assemblyName": "IgniteUI.Blazor.Documents.Excel" + }, + "content": [ + { + "files": [ + "api/**.yml", + "api/toc.yml" + ] + } + ], + "rawModelOutputFolder": "api-raw", + "dest": "api-json" + } +} \ No newline at end of file diff --git a/docfx-build-IgniteUI.Blazor.GridLite.json b/docfx-build-IgniteUI.Blazor.GridLite.json new file mode 100644 index 0000000..04e6fc5 --- /dev/null +++ b/docfx-build-IgniteUI.Blazor.GridLite.json @@ -0,0 +1,31 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ + "src/IgniteUI.Blazor.GridLite.dll" + ] + } + ], + "dest": "api", + "filter": "IgniteUI.Blazor.GridLite.filterConfig.yml" + } + ], + "build": { + "template": ["api-templates"], + "globalMetadata": { + "_assemblyName": "IgniteUI.Blazor.GridLite" + }, + "content": [ + { + "files": [ + "api/**.yml", + "api/toc.yml" + ] + } + ], + "rawModelOutputFolder": "api-raw", + "dest": "api-json" + } +} diff --git a/docfx-build-IgniteUI.Blazor.Lite.json b/docfx-build-IgniteUI.Blazor.Lite.json new file mode 100644 index 0000000..a45a400 --- /dev/null +++ b/docfx-build-IgniteUI.Blazor.Lite.json @@ -0,0 +1,30 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ + "src/IgniteUI.Blazor.Lite.dll" + ] + } + ], + "dest": "api" + } + ], + "build": { + "template": ["api-templates"], + "globalMetadata": { + "_assemblyName": "IgniteUI.Blazor.Lite" + }, + "content": [ + { + "files": [ + "api/**.yml", + "api/toc.yml" + ] + } + ], + "rawModelOutputFolder": "api-raw", + "dest": "api-json" + } +} diff --git a/docfx-build-IgniteUI.Blazor.json b/docfx-build-IgniteUI.Blazor.json new file mode 100644 index 0000000..b2d4251 --- /dev/null +++ b/docfx-build-IgniteUI.Blazor.json @@ -0,0 +1,31 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ + "src/IgniteUI.Blazor.dll" + ] + } + ], + "dest": "api", + "filter": "IgniteUI.Blazor.filterConfig.yml" + } + ], + "build": { + "template": ["api-templates"], + "globalMetadata": { + "_assemblyName": "IgniteUI.Blazor" + }, + "content": [ + { + "files": [ + "api/**.yml", + "api/toc.yml" + ] + } + ], + "rawModelOutputFolder": "api-raw", + "dest": "api-json" + } +} \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 0d62d3b..5c6e07e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -135,6 +135,7 @@ function buildDOC(callback) { exports.buildDOC = buildDOC; exports.run = gulp.series(updateIndex, copyIndex, buildDOC); +exports.prepare = gulp.series(updateIndex, copyIndex, copyBlazorSource); exports.build = gulp.series(clean, updateIndex, copyIndex, copyBlazorSource, buildAPI); // gulp.task('default', gulp.series('run')); diff --git a/package.json b/package.json index e6b12d4..263e38a 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,13 @@ }, "scripts": { "build": "gulp build", - "test": "echo \"Error: no test specified\" && exit 1" + "build:IgniteUI.Blazor": "gulp prepare && docfx docfx-build-IgniteUI.Blazor.json && node scripts/expand-toc.js", + "build:IgniteUI.Blazor.Documents.Core": "gulp prepare && docfx docfx-build-IgniteUI.Blazor.Documents.Core.json && node scripts/expand-toc.js", + "build:IgniteUI.Blazor.Documents.Excel": "gulp prepare && docfx docfx-build-IgniteUI.Blazor.Documents.Excel.json && node scripts/expand-toc.js", + "build:IgniteUI.Blazor.Lite": "gulp prepare && docfx docfx-build-IgniteUI.Blazor.Lite.json && node scripts/expand-toc.js", + "build:IgniteUI.Blazor.GridLite": "gulp prepare && docfx docfx-build-IgniteUI.Blazor.GridLite.json && node scripts/expand-toc.js", + "test": "echo \"Error: no test specified\" && exit 1", + "combine:toc": "node scripts/expand-toc.js" }, "author": "", "license": "ISC" diff --git a/scripts/expand-toc.js b/scripts/expand-toc.js new file mode 100644 index 0000000..8e2cc02 --- /dev/null +++ b/scripts/expand-toc.js @@ -0,0 +1,84 @@ +const fs = require('fs'); +const path = require('path'); + +const API_JSON_DIR = path.join(__dirname, '..', 'api-json', 'api'); +const TOC_PATH = path.join(API_JSON_DIR, 'toc.json'); + +function parseFile(filePath) { + try { + let fileContent = fs.readFileSync(filePath, 'utf-8'); + fileContent = fileContent.replace(/,\s*([\]}])/g, '$1'); + // Strip HTML tags from "text" values inside summary arrays + // to avoid unescaped quotes/attributes breaking JSON + fileContent = fileContent.replace(/"text":\s*"((?:[^"\\]|\\.)*)"/g, (match, val) => { + let clean = val; + // Decode HTML entities so we can strip the resulting HTML tags + clean = clean.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'"); + // Strip HTML tags + clean = clean.replace(/<[^>]*>/g, ''); + // Collapse whitespace and escaped newlines + clean = clean.replace(/\\n/g, ' ').replace(/\s+/g, ' ').trim(); + // Escape any double quotes for valid JSON + clean = clean.replace(/"/g, '\\"'); + return `"text": "${clean}"`; + }); + return JSON.parse(fileContent); + } catch (e) { + console.warn(`Warning: could not parse ${filePath}: ${e.message}`); + return {}; + } +} + +function expandItem(item) { + const ref = item.href || item.uid.replace(/`/g, '-') + '.json'; + const inheritedRef = item.inheritedFrom ? item.inheritedFrom + '.json' : null; + if (inheritedRef) { + const filePath = path.join(API_JSON_DIR, inheritedRef); + if (fs.existsSync(filePath)) { + const res = parseFile(filePath); + const child = res.children.find(c => c.uid === item.uid); + if (child) { + Object.assign(item, child); + } + } + } else if (ref) { + const filePath = path.join(API_JSON_DIR, ref); + if (fs.existsSync(filePath)) { + const res = parseFile(filePath); + Object.assign(item, res); + } + } + // Recurse into nested items + if (item.children && Array.isArray(item.children)) { + item.children.forEach(expandItem); + } +} + +// Read & fix trailing commas from Mustache output (e.g. single-item arrays) +let raw = fs.readFileSync(TOC_PATH, 'utf-8'); +raw = raw.replace(/,\s*([\]}])/g, '$1'); + +const toc = JSON.parse(raw); +toc.children.forEach(expandItem); + + + +const distDir = path.join(__dirname, '..', 'dist'); +if (!fs.existsSync(distDir)) { + fs.mkdirSync(distDir, { recursive: true }); +} + +const DIST_PATH = path.join(distDir, toc.name + '.json'); +const output = JSON.stringify(toc, (key, value) => { + if (typeof value === 'string') { + return value + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, "'"); + } + return value; +}, 2); +fs.writeFileSync(DIST_PATH, output, 'utf-8'); +console.log(`Expanded ${DIST_PATH} — all hrefs inlined.`);