From 0fa6d7819545c33bc5cb9887879e3b80e00930fc Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Tue, 17 Mar 2026 15:24:44 +0200 Subject: [PATCH 01/15] feat(export-json): Configure docfx with templates to export to json model + handing to merge model in 1 file. --- .gitignore | 2 + .../ManagedReference.json.primary.tmpl | 68 +++++++++++++++++++ api-templates/Toc.json.primary.tmpl | 18 +++++ docfx-build-IgniteUI.Blazor.json | 29 ++++++++ package.json | 1 + scripts/expand-toc.js | 52 ++++++++++++++ 6 files changed, 170 insertions(+) create mode 100644 api-templates/ManagedReference.json.primary.tmpl create mode 100644 api-templates/Toc.json.primary.tmpl create mode 100644 docfx-build-IgniteUI.Blazor.json create mode 100644 scripts/expand-toc.js diff --git a/.gitignore b/.gitignore index d94ea37..2e23a91 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ _site _site/** _site/*.* node_modules +api-json +api-raw # excluding IG assemblies and xml files src/*.dll diff --git a/api-templates/ManagedReference.json.primary.tmpl b/api-templates/ManagedReference.json.primary.tmpl new file mode 100644 index 0000000..2a1dd6b --- /dev/null +++ b/api-templates/ManagedReference.json.primary.tmpl @@ -0,0 +1,68 @@ +{ + "id": "{{uid}}", + "name": "{{name.0.value}}", + "fullName": "{{fullName.0.value}}", + "namespace": "{{namespace.uid}}", + "kind": "{{type}}", + "comment": { + "kind": "text", + "summary": "{{summary}}" + }, + "inheritance": [ + {{#if inheritance}} + {{#each inheritance}} + { + "id": "{{uid}}", + "name": "{{name.0.value}}" + }{{#unless @last}},{{/unless}} + {{/each}} + {{/if}} + ], + "implements": [ + {{#if implements}} + {{#each implements}} + { + "id": "{{uid}}", + "name": "{{name.0.value}}" + }{{#unless @last}},{{/unless}} + {{/each}} + {{/if}} + ], + "children": [ + {{#if children}} + {{#each children}} + { + "id": "{{uid}}", + "name": "{{name.0.value}}", + "fullName": "{{fullName.0.value}}", + "kind": "{{type}}", + "comment": { + "kind": "text", + "summary": "{{summary}}" + }, + {{#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..010048f --- /dev/null +++ b/api-templates/Toc.json.primary.tmpl @@ -0,0 +1,18 @@ +[ +{{#each items}} + { + "id": "{{topicUid}}", + "name": "{{name}}", + "href": "{{topicHref}}", + "children": [ + {{#each items}} + { + "id": "{{topicUid}}", + "name": "{{name}}", + "href": "{{topicHref}}" + }{{#unless @last}},{{/unless}} + {{/each}} + ] + }{{#unless @last}},{{/unless}} +{{/each}} +] diff --git a/docfx-build-IgniteUI.Blazor.json b/docfx-build-IgniteUI.Blazor.json new file mode 100644 index 0000000..33fcc04 --- /dev/null +++ b/docfx-build-IgniteUI.Blazor.json @@ -0,0 +1,29 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ + "src/IgniteUI.Blazor.dll" + ] + } + ], + "dest": "api" + } + ], + "build": { + "exportRawModel": true, + "exportViewModel": true, + "template": ["api-templates"], + "content": [ + { + "files": [ + "api/**.yml", + "api/toc.yml" + ] + } + ], + "rawModelOutputFolder": "api-raw", + "dest": "api-json" + } +} \ No newline at end of file diff --git a/package.json b/package.json index e6b12d4..efe5ec2 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ }, "scripts": { "build": "gulp build", + "build:docs": "docfx docfx-build-IgniteUI.Blazor.json && node scripts/expand-toc.js", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", diff --git a/scripts/expand-toc.js b/scripts/expand-toc.js new file mode 100644 index 0000000..e2e6249 --- /dev/null +++ b/scripts/expand-toc.js @@ -0,0 +1,52 @@ +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 expandItem(item) { + if (item.href) { + const filePath = path.join(API_JSON_DIR, item.href); + if (fs.existsSync(filePath)) { + try { + let fileContent = fs.readFileSync(filePath, 'utf-8'); + fileContent = fileContent.replace(/,\s*([\]}])/g, '$1'); + // Strip HTML tags from summary values before parsing + // to avoid unescaped quotes/attributes breaking JSON + fileContent = fileContent.replace(/"summary":\s*"((?:[^"\\]|\\.)*)"/g, (match, val) => { + let clean = val; + // Decode HTML entities first + 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 `"summary": "${clean}"`; + }); + const content = JSON.parse(fileContent); + // Replace href with the actual JSON content + delete item.href; + Object.assign(item, content); + } catch (e) { + console.warn(`Warning: could not parse ${item.href}: ${e.message}`); + } + } + } + // Recurse into nested items + if (item.items && Array.isArray(item.items)) { + item.items.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.forEach(expandItem); + +fs.writeFileSync(TOC_PATH, JSON.stringify(toc, null, 2), 'utf-8'); +console.log(`Expanded ${TOC_PATH} — all hrefs inlined.`); From dc14d1e88c877bcc258641c32b075dc9aab15975 Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Tue, 17 Mar 2026 15:49:33 +0200 Subject: [PATCH 02/15] feat(toc-expansion): Update expand-toc.js handle hierarchy correctly. --- package.json | 3 ++- scripts/expand-toc.js | 18 +++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index efe5ec2..799e1ba 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "scripts": { "build": "gulp build", "build:docs": "docfx docfx-build-IgniteUI.Blazor.json && node scripts/expand-toc.js", - "test": "echo \"Error: no test specified\" && exit 1" + "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 index e2e6249..a31d605 100644 --- a/scripts/expand-toc.js +++ b/scripts/expand-toc.js @@ -3,10 +3,12 @@ const path = require('path'); const API_JSON_DIR = path.join(__dirname, '..', 'api-json', 'api'); const TOC_PATH = path.join(API_JSON_DIR, 'toc.json'); +const TOC_PATH_2 = path.join(__dirname, '..', 'api-json', 'IgniteUI.Blazor.json'); function expandItem(item) { - if (item.href) { - const filePath = path.join(API_JSON_DIR, item.href); + const ref = item.href || item.id + '.json'; + if (ref) { + const filePath = path.join(API_JSON_DIR, ref); if (fs.existsSync(filePath)) { try { let fileContent = fs.readFileSync(filePath, 'utf-8'); @@ -26,17 +28,15 @@ function expandItem(item) { return `"summary": "${clean}"`; }); const content = JSON.parse(fileContent); - // Replace href with the actual JSON content - delete item.href; Object.assign(item, content); } catch (e) { - console.warn(`Warning: could not parse ${item.href}: ${e.message}`); + console.warn(`Warning: could not parse ${ref}: ${e.message}`); } } } // Recurse into nested items - if (item.items && Array.isArray(item.items)) { - item.items.forEach(expandItem); + if (item.children && Array.isArray(item.children)) { + item.children.forEach(expandItem); } } @@ -48,5 +48,5 @@ const toc = JSON.parse(raw); toc.forEach(expandItem); -fs.writeFileSync(TOC_PATH, JSON.stringify(toc, null, 2), 'utf-8'); -console.log(`Expanded ${TOC_PATH} — all hrefs inlined.`); +fs.writeFileSync(TOC_PATH_2, JSON.stringify(toc, null, 2), 'utf-8'); +console.log(`Expanded ${TOC_PATH_2} — all hrefs inlined.`); From 7776304bf5e52bbe35fd480b24a34f4f104df136 Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Tue, 17 Mar 2026 16:03:48 +0200 Subject: [PATCH 03/15] fix(api-json): Add filter to metadata destination and remove href from expanded items --- docfx-build-IgniteUI.Blazor.json | 3 ++- scripts/expand-toc.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docfx-build-IgniteUI.Blazor.json b/docfx-build-IgniteUI.Blazor.json index 33fcc04..afc255d 100644 --- a/docfx-build-IgniteUI.Blazor.json +++ b/docfx-build-IgniteUI.Blazor.json @@ -8,7 +8,8 @@ ] } ], - "dest": "api" + "dest": "api", + "filter": "filterConfig.yml" } ], "build": { diff --git a/scripts/expand-toc.js b/scripts/expand-toc.js index a31d605..b59b379 100644 --- a/scripts/expand-toc.js +++ b/scripts/expand-toc.js @@ -29,6 +29,7 @@ function expandItem(item) { }); const content = JSON.parse(fileContent); Object.assign(item, content); + delete item.href; } catch (e) { console.warn(`Warning: could not parse ${ref}: ${e.message}`); } From d6adf31a26a56c8e449d151a5dc00e331c18c0a4 Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Tue, 17 Mar 2026 18:31:01 +0200 Subject: [PATCH 04/15] Use IgniteUI.Blazor.Controls as root since all component classes are inside. --- .../ManagedReference.json.primary.tmpl | 32 +++++++++++++------ api-templates/Toc.json.primary.tmpl | 22 +++---------- scripts/expand-toc.js | 12 +++---- 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/api-templates/ManagedReference.json.primary.tmpl b/api-templates/ManagedReference.json.primary.tmpl index 2a1dd6b..3b3c2cc 100644 --- a/api-templates/ManagedReference.json.primary.tmpl +++ b/api-templates/ManagedReference.json.primary.tmpl @@ -1,18 +1,24 @@ { - "id": "{{uid}}", + "uid": "{{uid}}", + "id": 0, "name": "{{name.0.value}}", "fullName": "{{fullName.0.value}}", "namespace": "{{namespace.uid}}", - "kind": "{{type}}", + "kindString": "{{type}}", "comment": { - "kind": "text", - "summary": "{{summary}}" + "summary": [ + { + "kindString": "text", + "text": "{{summary}}" + } + ] }, "inheritance": [ {{#if inheritance}} {{#each inheritance}} { - "id": "{{uid}}", + "uid": "{{uid}}", + "id": 0, "name": "{{name.0.value}}" }{{#unless @last}},{{/unless}} {{/each}} @@ -22,7 +28,8 @@ {{#if implements}} {{#each implements}} { - "id": "{{uid}}", + "uid": "{{uid}}", + "id": 0, "name": "{{name.0.value}}" }{{#unless @last}},{{/unless}} {{/each}} @@ -32,13 +39,18 @@ {{#if children}} {{#each children}} { - "id": "{{uid}}", + "uid": "{{uid}}", + "id": 0, "name": "{{name.0.value}}", "fullName": "{{fullName.0.value}}", - "kind": "{{type}}", + "kindString": "{{type}}", "comment": { - "kind": "text", - "summary": "{{summary}}" + "summary": [ + { + "kindString": "text", + "text": "{{summary}}" + } + ] }, {{#if syntax}} "syntax": { diff --git a/api-templates/Toc.json.primary.tmpl b/api-templates/Toc.json.primary.tmpl index 010048f..00350c7 100644 --- a/api-templates/Toc.json.primary.tmpl +++ b/api-templates/Toc.json.primary.tmpl @@ -1,18 +1,4 @@ -[ -{{#each items}} - { - "id": "{{topicUid}}", - "name": "{{name}}", - "href": "{{topicHref}}", - "children": [ - {{#each items}} - { - "id": "{{topicUid}}", - "name": "{{name}}", - "href": "{{topicHref}}" - }{{#unless @last}},{{/unless}} - {{/each}} - ] - }{{#unless @last}},{{/unless}} -{{/each}} -] +{ +"uid": "IgniteUI.Blazor.Controls", +"name": "IgniteUI.Blazor.Controls", +} diff --git a/scripts/expand-toc.js b/scripts/expand-toc.js index b59b379..7e01a42 100644 --- a/scripts/expand-toc.js +++ b/scripts/expand-toc.js @@ -6,16 +6,16 @@ const TOC_PATH = path.join(API_JSON_DIR, 'toc.json'); const TOC_PATH_2 = path.join(__dirname, '..', 'api-json', 'IgniteUI.Blazor.json'); function expandItem(item) { - const ref = item.href || item.id + '.json'; + const ref = item.href || item.uid + '.json'; if (ref) { const filePath = path.join(API_JSON_DIR, ref); if (fs.existsSync(filePath)) { try { let fileContent = fs.readFileSync(filePath, 'utf-8'); fileContent = fileContent.replace(/,\s*([\]}])/g, '$1'); - // Strip HTML tags from summary values before parsing + // Strip HTML tags from "text" values inside summary arrays // to avoid unescaped quotes/attributes breaking JSON - fileContent = fileContent.replace(/"summary":\s*"((?:[^"\\]|\\.)*)"/g, (match, val) => { + fileContent = fileContent.replace(/"text":\s*"((?:[^"\\]|\\.)*)"/g, (match, val) => { let clean = val; // Decode HTML entities first clean = clean.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/&/g, '&').replace(/'/g, "'"); @@ -25,7 +25,7 @@ function expandItem(item) { clean = clean.replace(/\\n/g, ' ').replace(/\s+/g, ' ').trim(); // Escape any double quotes for valid JSON clean = clean.replace(/"/g, '\\"'); - return `"summary": "${clean}"`; + return `"text": "${clean}"`; }); const content = JSON.parse(fileContent); Object.assign(item, content); @@ -46,8 +46,8 @@ let raw = fs.readFileSync(TOC_PATH, 'utf-8'); raw = raw.replace(/,\s*([\]}])/g, '$1'); const toc = JSON.parse(raw); - -toc.forEach(expandItem); +expandItem(toc); +// toc.children.forEach(expandItem); fs.writeFileSync(TOC_PATH_2, JSON.stringify(toc, null, 2), 'utf-8'); console.log(`Expanded ${TOC_PATH_2} — all hrefs inlined.`); From 73bc20fdb102110f4664e1b896ebd48b4707f8f7 Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Wed, 18 Mar 2026 14:16:01 +0200 Subject: [PATCH 05/15] Filter out some of the namespaces and classes we don't want in public docs. --- IgniteUI.Blazor.filterConfig.yml | 13 +++++++++++++ docfx-build-IgniteUI.Blazor.json | 4 +--- package.json | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 IgniteUI.Blazor.filterConfig.yml diff --git a/IgniteUI.Blazor.filterConfig.yml b/IgniteUI.Blazor.filterConfig.yml new file mode 100644 index 0000000..9a94df5 --- /dev/null +++ b/IgniteUI.Blazor.filterConfig.yml @@ -0,0 +1,13 @@ +apiRules: +- exclude: + uidRegex: ^IgniteUI\.Blazor\._Imports$ + type: Class +- exclude: + uidRegex: ^IgniteUI\.Blazor\.Controls\.Description + type: Namespace +- exclude: + uidRegex: ^System\.Runtime\.CompilerServices\. + type: Class +- exclude: + uidRegex: ^IgniteUI\.Blazor\.Controls\.Util\. + type: Class \ No newline at end of file diff --git a/docfx-build-IgniteUI.Blazor.json b/docfx-build-IgniteUI.Blazor.json index afc255d..df96368 100644 --- a/docfx-build-IgniteUI.Blazor.json +++ b/docfx-build-IgniteUI.Blazor.json @@ -9,12 +9,10 @@ } ], "dest": "api", - "filter": "filterConfig.yml" + "filter": "IgniteUI.Blazor.filterConfig.yml" } ], "build": { - "exportRawModel": true, - "exportViewModel": true, "template": ["api-templates"], "content": [ { diff --git a/package.json b/package.json index 799e1ba..9e70a66 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "scripts": { "build": "gulp build", - "build:docs": "docfx docfx-build-IgniteUI.Blazor.json && node scripts/expand-toc.js", + "build:IgniteUI.Blazor": "docfx docfx-build-IgniteUI.Blazor.json && node scripts/expand-toc.js", "test": "echo \"Error: no test specified\" && exit 1", "combine:toc": "node scripts/expand-toc.js" }, From eaa44521e3687181332e810a86c2917e891b12b4 Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Wed, 18 Mar 2026 14:57:40 +0200 Subject: [PATCH 06/15] Tweaks for structure. --- api-templates/Toc.json.primary.tmpl | 16 +++++++++++++--- docfx-build-IgniteUI.Blazor.json | 3 +++ scripts/expand-toc.js | 6 +++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/api-templates/Toc.json.primary.tmpl b/api-templates/Toc.json.primary.tmpl index 00350c7..d60a06c 100644 --- a/api-templates/Toc.json.primary.tmpl +++ b/api-templates/Toc.json.primary.tmpl @@ -1,4 +1,14 @@ { -"uid": "IgniteUI.Blazor.Controls", -"name": "IgniteUI.Blazor.Controls", -} +"name": "{{_assemblyName}}", +"children": [ + {{#each items}} + {{#each items}} + { + "uid": "{{topicUid}}", + "name": "{{name}}", + "href": "{{topicHref}}" + }, + {{/each}} + {{/each}} +] +} \ No newline at end of file diff --git a/docfx-build-IgniteUI.Blazor.json b/docfx-build-IgniteUI.Blazor.json index df96368..b2d4251 100644 --- a/docfx-build-IgniteUI.Blazor.json +++ b/docfx-build-IgniteUI.Blazor.json @@ -14,6 +14,9 @@ ], "build": { "template": ["api-templates"], + "globalMetadata": { + "_assemblyName": "IgniteUI.Blazor" + }, "content": [ { "files": [ diff --git a/scripts/expand-toc.js b/scripts/expand-toc.js index 7e01a42..38bcb81 100644 --- a/scripts/expand-toc.js +++ b/scripts/expand-toc.js @@ -3,7 +3,7 @@ const path = require('path'); const API_JSON_DIR = path.join(__dirname, '..', 'api-json', 'api'); const TOC_PATH = path.join(API_JSON_DIR, 'toc.json'); -const TOC_PATH_2 = path.join(__dirname, '..', 'api-json', 'IgniteUI.Blazor.json'); + function expandItem(item) { const ref = item.href || item.uid + '.json'; @@ -46,8 +46,8 @@ let raw = fs.readFileSync(TOC_PATH, 'utf-8'); raw = raw.replace(/,\s*([\]}])/g, '$1'); const toc = JSON.parse(raw); -expandItem(toc); -// toc.children.forEach(expandItem); +toc.children.forEach(expandItem); +const TOC_PATH_2 = path.join(__dirname, '..', 'api-json', toc.name + '.json'); fs.writeFileSync(TOC_PATH_2, JSON.stringify(toc, null, 2), 'utf-8'); console.log(`Expanded ${TOC_PATH_2} — all hrefs inlined.`); From 098bdee11b60780957cbbe0dc92b6b888ca854ff Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Wed, 18 Mar 2026 15:01:03 +0200 Subject: [PATCH 07/15] Minor tweaks for output. --- .gitignore | 1 + scripts/expand-toc.js | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 2e23a91..07d260c 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ _site/*.* node_modules api-json api-raw +dist # excluding IG assemblies and xml files src/*.dll diff --git a/scripts/expand-toc.js b/scripts/expand-toc.js index 38bcb81..c312cf6 100644 --- a/scripts/expand-toc.js +++ b/scripts/expand-toc.js @@ -48,6 +48,11 @@ raw = raw.replace(/,\s*([\]}])/g, '$1'); const toc = JSON.parse(raw); toc.children.forEach(expandItem); -const TOC_PATH_2 = path.join(__dirname, '..', 'api-json', toc.name + '.json'); -fs.writeFileSync(TOC_PATH_2, JSON.stringify(toc, null, 2), 'utf-8'); -console.log(`Expanded ${TOC_PATH_2} — all hrefs inlined.`); +const distDir = path.join(__dirname, '..', 'dist'); +if (!fs.existsSync(distDir)) { + fs.mkdirSync(distDir, { recursive: true }); +} + +const DIST_PATH = path.join(distDir, toc.name + '.json'); +fs.writeFileSync(DIST_PATH, JSON.stringify(toc, null, 2), 'utf-8'); +console.log(`Expanded ${DIST_PATH} — all hrefs inlined.`); From eb7ab9a2e273339a2d7b7599111b2c4d8da40e80 Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Wed, 18 Mar 2026 16:03:51 +0200 Subject: [PATCH 08/15] Add docfx configs and tasks for other assemblies. Add namespaces to json. --- api-templates/Toc.json.primary.tmpl | 7 ++--- ...-build-IgniteUI.Blazor.Documents.Core.json | 30 +++++++++++++++++++ ...build-IgniteUI.Blazor.Documents.Excel.json | 30 +++++++++++++++++++ package.json | 2 ++ 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 docfx-build-IgniteUI.Blazor.Documents.Core.json create mode 100644 docfx-build-IgniteUI.Blazor.Documents.Excel.json diff --git a/api-templates/Toc.json.primary.tmpl b/api-templates/Toc.json.primary.tmpl index d60a06c..d518628 100644 --- a/api-templates/Toc.json.primary.tmpl +++ b/api-templates/Toc.json.primary.tmpl @@ -1,14 +1,13 @@ { "name": "{{_assemblyName}}", "children": [ - {{#each items}} {{#each items}} { "uid": "{{topicUid}}", "name": "{{name}}", - "href": "{{topicHref}}" - }, - {{/each}} + "href": "{{topicHref}}", + "kindString": "{{type}}" + }{{#unless @last}},{{/unless}} {{/each}} ] } \ No newline at end of file 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/package.json b/package.json index 9e70a66..de46b63 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,8 @@ "scripts": { "build": "gulp build", "build:IgniteUI.Blazor": "docfx docfx-build-IgniteUI.Blazor.json && node scripts/expand-toc.js", + "build:IgniteUI.Blazor.Documents.Core": "docfx docfx-build-IgniteUI.Blazor.Documents.Core.json && node scripts/expand-toc.js", + "build:IgniteUI.Blazor.Documents.Excel": "docfx docfx-build-IgniteUI.Blazor.Documents.Excel.json && node scripts/expand-toc.js", "test": "echo \"Error: no test specified\" && exit 1", "combine:toc": "node scripts/expand-toc.js" }, From d5c7923b0959fc78fa90557a90f470e1b37e8cb5 Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Wed, 18 Mar 2026 17:16:02 +0200 Subject: [PATCH 09/15] Add the other packages as well. --- IgniteUI.Blazor.GridLite.filterConfig.yml | 16 ++++++++ IgniteUI.Blazor.filterConfig.yml | 3 -- app/blazor-app.csproj | 50 ++++++++++++++++------- docfx-build-IgniteUI.Blazor.GridLite.json | 31 ++++++++++++++ docfx-build-IgniteUI.Blazor.Lite.json | 30 ++++++++++++++ gulpfile.js | 1 + package.json | 3 ++ 7 files changed, 117 insertions(+), 17 deletions(-) create mode 100644 IgniteUI.Blazor.GridLite.filterConfig.yml create mode 100644 docfx-build-IgniteUI.Blazor.GridLite.json create mode 100644 docfx-build-IgniteUI.Blazor.Lite.json 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 index 9a94df5..576444a 100644 --- a/IgniteUI.Blazor.filterConfig.yml +++ b/IgniteUI.Blazor.filterConfig.yml @@ -7,7 +7,4 @@ apiRules: type: Namespace - exclude: uidRegex: ^System\.Runtime\.CompilerServices\. - type: Class -- exclude: - uidRegex: ^IgniteUI\.Blazor\.Controls\.Util\. type: Class \ 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.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/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 de46b63..fd59f47 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,12 @@ }, "scripts": { "build": "gulp build", + "prepare": "gulp prepare", "build:IgniteUI.Blazor": "docfx docfx-build-IgniteUI.Blazor.json && node scripts/expand-toc.js", "build:IgniteUI.Blazor.Documents.Core": "docfx docfx-build-IgniteUI.Blazor.Documents.Core.json && node scripts/expand-toc.js", "build:IgniteUI.Blazor.Documents.Excel": "docfx docfx-build-IgniteUI.Blazor.Documents.Excel.json && node scripts/expand-toc.js", + "build:IgniteUI.Blazor.Lite": "docfx docfx-build-IgniteUI.Blazor.Lite.json && node scripts/expand-toc.js", + "build:IgniteUI.Blazor.GridLite": "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" }, From 58489c534a296fb2b78363adfaa493448bf97d92 Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Thu, 19 Mar 2026 10:07:49 +0200 Subject: [PATCH 10/15] Include step that build proj and copies assemblies before building. --- package.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index fd59f47..263e38a 100644 --- a/package.json +++ b/package.json @@ -14,12 +14,11 @@ }, "scripts": { "build": "gulp build", - "prepare": "gulp prepare", - "build:IgniteUI.Blazor": "docfx docfx-build-IgniteUI.Blazor.json && node scripts/expand-toc.js", - "build:IgniteUI.Blazor.Documents.Core": "docfx docfx-build-IgniteUI.Blazor.Documents.Core.json && node scripts/expand-toc.js", - "build:IgniteUI.Blazor.Documents.Excel": "docfx docfx-build-IgniteUI.Blazor.Documents.Excel.json && node scripts/expand-toc.js", - "build:IgniteUI.Blazor.Lite": "docfx docfx-build-IgniteUI.Blazor.Lite.json && node scripts/expand-toc.js", - "build:IgniteUI.Blazor.GridLite": "docfx docfx-build-IgniteUI.Blazor.GridLite.json && node scripts/expand-toc.js", + "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" }, From 95c7362582f19073c91e7d369737227759c43118 Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Thu, 19 Mar 2026 14:59:02 +0200 Subject: [PATCH 11/15] More HTML entity decoding. --- scripts/expand-toc.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/scripts/expand-toc.js b/scripts/expand-toc.js index c312cf6..ea7800c 100644 --- a/scripts/expand-toc.js +++ b/scripts/expand-toc.js @@ -17,8 +17,8 @@ function expandItem(item) { // to avoid unescaped quotes/attributes breaking JSON fileContent = fileContent.replace(/"text":\s*"((?:[^"\\]|\\.)*)"/g, (match, val) => { let clean = val; - // Decode HTML entities first - clean = clean.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/&/g, '&').replace(/'/g, "'"); + // 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 @@ -48,11 +48,24 @@ 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'); -fs.writeFileSync(DIST_PATH, JSON.stringify(toc, null, 2), 'utf-8'); +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.`); From b3ba80c491284dd2a322ea21058702e7197b67fc Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Thu, 19 Mar 2026 15:11:12 +0200 Subject: [PATCH 12/15] Fix paths due to special chars in uid. --- scripts/expand-toc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/expand-toc.js b/scripts/expand-toc.js index ea7800c..cb5b5c7 100644 --- a/scripts/expand-toc.js +++ b/scripts/expand-toc.js @@ -6,7 +6,7 @@ const TOC_PATH = path.join(API_JSON_DIR, 'toc.json'); function expandItem(item) { - const ref = item.href || item.uid + '.json'; + const ref = item.href || item.uid.replace(/`/g, '-') + '.json'; if (ref) { const filePath = path.join(API_JSON_DIR, ref); if (fs.existsSync(filePath)) { From f4bbdbab14e06be7ba494fe84e32c3feda9f18db Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Tue, 24 Mar 2026 16:17:51 +0200 Subject: [PATCH 13/15] Extract inherited members and code example. --- .../ManagedReference.json.primary.tmpl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/api-templates/ManagedReference.json.primary.tmpl b/api-templates/ManagedReference.json.primary.tmpl index 3b3c2cc..bcd9e0f 100644 --- a/api-templates/ManagedReference.json.primary.tmpl +++ b/api-templates/ManagedReference.json.primary.tmpl @@ -10,6 +10,10 @@ { "kindString": "text", "text": "{{summary}}" + }, + { + "kindString": "code", + "text": "{{syntax.content.0.value}}" } ] }, @@ -35,6 +39,16 @@ {{/each}} {{/if}} ], + "inheritedMembers": [ + {{#if inheritedMembers}} + {{#each inheritedMembers}} + { + "id": 0, + "name": "{{name.0.value}}" + }{{#unless @last}},{{/unless}} + {{/each}} + {{/if}} + ], "children": [ {{#if children}} {{#each children}} @@ -49,6 +63,10 @@ { "kindString": "text", "text": "{{summary}}" + }, + { + "kindString": "code", + "text": "{{syntax.content.0.value}}" } ] }, From 45d9000a4eaaadd3a058dce6b393eb86ae230858 Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Tue, 24 Mar 2026 17:40:35 +0200 Subject: [PATCH 14/15] Merge all members to single collection. --- .../ManagedReference.json.primary.js | 14 ++++++ .../ManagedReference.json.primary.tmpl | 43 +++++++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 api-templates/ManagedReference.json.primary.js 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 index bcd9e0f..fc64301 100644 --- a/api-templates/ManagedReference.json.primary.tmpl +++ b/api-templates/ManagedReference.json.primary.tmpl @@ -39,17 +39,52 @@ {{/each}} {{/if}} ], - "inheritedMembers": [ + "children": [ {{#if inheritedMembers}} {{#each inheritedMembers}} { + "uid": "{{uid}}", "id": 0, - "name": "{{name.0.value}}" + "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}} - ], - "children": [ {{#if children}} {{#each children}} { From 128c6c3e8362a3992509a8015f77866f68d1d7c4 Mon Sep 17 00:00:00 2001 From: Maya Kirova Date: Wed, 25 Mar 2026 16:42:24 +0200 Subject: [PATCH 15/15] Expand inherited members info. --- scripts/expand-toc.js | 61 ++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/scripts/expand-toc.js b/scripts/expand-toc.js index cb5b5c7..8e2cc02 100644 --- a/scripts/expand-toc.js +++ b/scripts/expand-toc.js @@ -4,36 +4,49 @@ 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'; - if (ref) { - const filePath = path.join(API_JSON_DIR, ref); + const inheritedRef = item.inheritedFrom ? item.inheritedFrom + '.json' : null; + if (inheritedRef) { + const filePath = path.join(API_JSON_DIR, inheritedRef); if (fs.existsSync(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}"`; - }); - const content = JSON.parse(fileContent); - Object.assign(item, content); - delete item.href; - } catch (e) { - console.warn(`Warning: could not parse ${ref}: ${e.message}`); + 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)) {