This is page 21 of 23. Use http://codebase.md/tosin2013/documcp?lines=false&page={x} to view the full context.
# Directory Structure
```
├── .dockerignore
├── .eslintignore
├── .eslintrc.json
├── .github
│ ├── agents
│ │ ├── documcp-ast.md
│ │ ├── documcp-deploy.md
│ │ ├── documcp-memory.md
│ │ ├── documcp-test.md
│ │ └── documcp-tool.md
│ ├── copilot-instructions.md
│ ├── dependabot.yml
│ ├── ISSUE_TEMPLATE
│ │ ├── automated-changelog.md
│ │ ├── bug_report.md
│ │ ├── bug_report.yml
│ │ ├── documentation_issue.md
│ │ ├── feature_request.md
│ │ ├── feature_request.yml
│ │ ├── npm-publishing-fix.md
│ │ └── release_improvements.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── release-drafter.yml
│ └── workflows
│ ├── auto-merge.yml
│ ├── ci.yml
│ ├── codeql.yml
│ ├── dependency-review.yml
│ ├── deploy-docs.yml
│ ├── README.md
│ ├── release-drafter.yml
│ └── release.yml
├── .gitignore
├── .husky
│ ├── commit-msg
│ └── pre-commit
├── .linkcheck.config.json
├── .markdown-link-check.json
├── .nvmrc
├── .pre-commit-config.yaml
├── .versionrc.json
├── ARCHITECTURAL_CHANGES_SUMMARY.md
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── commitlint.config.js
├── CONTRIBUTING.md
├── docker-compose.docs.yml
├── Dockerfile.docs
├── docs
│ ├── .docusaurus
│ │ ├── docusaurus-plugin-content-docs
│ │ │ └── default
│ │ │ └── __mdx-loader-dependency.json
│ │ └── docusaurus-plugin-content-pages
│ │ └── default
│ │ └── __plugin.json
│ ├── adrs
│ │ ├── adr-0001-mcp-server-architecture.md
│ │ ├── adr-0002-repository-analysis-engine.md
│ │ ├── adr-0003-static-site-generator-recommendation-engine.md
│ │ ├── adr-0004-diataxis-framework-integration.md
│ │ ├── adr-0005-github-pages-deployment-automation.md
│ │ ├── adr-0006-mcp-tools-api-design.md
│ │ ├── adr-0007-mcp-prompts-and-resources-integration.md
│ │ ├── adr-0008-intelligent-content-population-engine.md
│ │ ├── adr-0009-content-accuracy-validation-framework.md
│ │ ├── adr-0010-mcp-resource-pattern-redesign.md
│ │ ├── adr-0011-ce-mcp-compatibility.md
│ │ ├── adr-0012-priority-scoring-system-for-documentation-drift.md
│ │ ├── adr-0013-release-pipeline-and-package-distribution.md
│ │ └── README.md
│ ├── api
│ │ ├── .nojekyll
│ │ ├── assets
│ │ │ ├── hierarchy.js
│ │ │ ├── highlight.css
│ │ │ ├── icons.js
│ │ │ ├── icons.svg
│ │ │ ├── main.js
│ │ │ ├── navigation.js
│ │ │ ├── search.js
│ │ │ └── style.css
│ │ ├── hierarchy.html
│ │ ├── index.html
│ │ ├── modules.html
│ │ └── variables
│ │ └── TOOLS.html
│ ├── assets
│ │ └── logo.svg
│ ├── CE-MCP-FINDINGS.md
│ ├── development
│ │ └── MCP_INSPECTOR_TESTING.md
│ ├── docusaurus.config.js
│ ├── explanation
│ │ ├── architecture.md
│ │ └── index.md
│ ├── guides
│ │ ├── link-validation.md
│ │ ├── playwright-integration.md
│ │ └── playwright-testing-workflow.md
│ ├── how-to
│ │ ├── analytics-setup.md
│ │ ├── change-watcher.md
│ │ ├── custom-domains.md
│ │ ├── documentation-freshness-tracking.md
│ │ ├── drift-priority-scoring.md
│ │ ├── github-pages-deployment.md
│ │ ├── index.md
│ │ ├── llm-integration.md
│ │ ├── local-testing.md
│ │ ├── performance-optimization.md
│ │ ├── prompting-guide.md
│ │ ├── repository-analysis.md
│ │ ├── seo-optimization.md
│ │ ├── site-monitoring.md
│ │ ├── troubleshooting.md
│ │ └── usage-examples.md
│ ├── index.md
│ ├── knowledge-graph.md
│ ├── package-lock.json
│ ├── package.json
│ ├── phase-2-intelligence.md
│ ├── reference
│ │ ├── api-overview.md
│ │ ├── cli.md
│ │ ├── configuration.md
│ │ ├── deploy-pages.md
│ │ ├── index.md
│ │ ├── mcp-tools.md
│ │ └── prompt-templates.md
│ ├── research
│ │ ├── cross-domain-integration
│ │ │ └── README.md
│ │ ├── domain-1-mcp-architecture
│ │ │ ├── index.md
│ │ │ └── mcp-performance-research.md
│ │ ├── domain-2-repository-analysis
│ │ │ └── README.md
│ │ ├── domain-3-ssg-recommendation
│ │ │ ├── index.md
│ │ │ └── ssg-performance-analysis.md
│ │ ├── domain-4-diataxis-integration
│ │ │ └── README.md
│ │ ├── domain-5-github-deployment
│ │ │ ├── github-pages-security-analysis.md
│ │ │ └── index.md
│ │ ├── domain-6-api-design
│ │ │ └── README.md
│ │ ├── README.md
│ │ ├── research-integration-summary-2025-01-14.md
│ │ ├── research-progress-template.md
│ │ └── research-questions-2025-01-14.md
│ ├── robots.txt
│ ├── sidebars.js
│ ├── sitemap.xml
│ ├── src
│ │ └── css
│ │ └── custom.css
│ └── tutorials
│ ├── development-setup.md
│ ├── environment-setup.md
│ ├── first-deployment.md
│ ├── getting-started.md
│ ├── index.md
│ ├── memory-workflows.md
│ └── user-onboarding.md
├── ISSUE_IMPLEMENTATION_SUMMARY.md
├── jest.config.js
├── LICENSE
├── Makefile
├── MCP_PHASE2_IMPLEMENTATION.md
├── mcp-config-example.json
├── mcp.json
├── package-lock.json
├── package.json
├── README.md
├── release.sh
├── scripts
│ └── check-package-structure.cjs
├── SECURITY.md
├── setup-precommit.sh
├── src
│ ├── benchmarks
│ │ └── performance.ts
│ ├── index.ts
│ ├── memory
│ │ ├── contextual-retrieval.ts
│ │ ├── deployment-analytics.ts
│ │ ├── enhanced-manager.ts
│ │ ├── export-import.ts
│ │ ├── freshness-kg-integration.ts
│ │ ├── index.ts
│ │ ├── integration.ts
│ │ ├── kg-code-integration.ts
│ │ ├── kg-health.ts
│ │ ├── kg-integration.ts
│ │ ├── kg-link-validator.ts
│ │ ├── kg-storage.ts
│ │ ├── knowledge-graph.ts
│ │ ├── learning.ts
│ │ ├── manager.ts
│ │ ├── multi-agent-sharing.ts
│ │ ├── pruning.ts
│ │ ├── schemas.ts
│ │ ├── storage.ts
│ │ ├── temporal-analysis.ts
│ │ ├── user-preferences.ts
│ │ └── visualization.ts
│ ├── prompts
│ │ └── technical-writer-prompts.ts
│ ├── scripts
│ │ └── benchmark.ts
│ ├── templates
│ │ └── playwright
│ │ ├── accessibility.spec.template.ts
│ │ ├── Dockerfile.template
│ │ ├── docs-e2e.workflow.template.yml
│ │ ├── link-validation.spec.template.ts
│ │ └── playwright.config.template.ts
│ ├── tools
│ │ ├── analyze-deployments.ts
│ │ ├── analyze-readme.ts
│ │ ├── analyze-repository.ts
│ │ ├── change-watcher.ts
│ │ ├── check-documentation-links.ts
│ │ ├── cleanup-agent-artifacts.ts
│ │ ├── deploy-pages.ts
│ │ ├── detect-gaps.ts
│ │ ├── evaluate-readme-health.ts
│ │ ├── generate-config.ts
│ │ ├── generate-contextual-content.ts
│ │ ├── generate-llm-context.ts
│ │ ├── generate-readme-template.ts
│ │ ├── generate-technical-writer-prompts.ts
│ │ ├── kg-health-check.ts
│ │ ├── manage-preferences.ts
│ │ ├── manage-sitemap.ts
│ │ ├── optimize-readme.ts
│ │ ├── populate-content.ts
│ │ ├── readme-best-practices.ts
│ │ ├── recommend-ssg.ts
│ │ ├── setup-playwright-tests.ts
│ │ ├── setup-structure.ts
│ │ ├── simulate-execution.ts
│ │ ├── sync-code-to-docs.ts
│ │ ├── test-local-deployment.ts
│ │ ├── track-documentation-freshness.ts
│ │ ├── update-existing-documentation.ts
│ │ ├── validate-content.ts
│ │ ├── validate-documentation-freshness.ts
│ │ ├── validate-readme-checklist.ts
│ │ └── verify-deployment.ts
│ ├── types
│ │ └── api.ts
│ ├── utils
│ │ ├── artifact-detector.ts
│ │ ├── ast-analyzer.ts
│ │ ├── change-watcher.ts
│ │ ├── code-scanner.ts
│ │ ├── content-extractor.ts
│ │ ├── drift-detector.ts
│ │ ├── execution-simulator.ts
│ │ ├── freshness-tracker.ts
│ │ ├── language-parsers-simple.ts
│ │ ├── llm-client.ts
│ │ ├── permission-checker.ts
│ │ ├── semantic-analyzer.ts
│ │ ├── sitemap-generator.ts
│ │ ├── usage-metadata.ts
│ │ └── user-feedback-integration.ts
│ └── workflows
│ └── documentation-workflow.ts
├── test-docs-local.sh
├── tests
│ ├── api
│ │ └── mcp-responses.test.ts
│ ├── benchmarks
│ │ └── performance.test.ts
│ ├── call-graph-builder.test.ts
│ ├── change-watcher-priority.integration.test.ts
│ ├── change-watcher.test.ts
│ ├── edge-cases
│ │ └── error-handling.test.ts
│ ├── execution-simulator.test.ts
│ ├── functional
│ │ └── tools.test.ts
│ ├── integration
│ │ ├── kg-documentation-workflow.test.ts
│ │ ├── knowledge-graph-workflow.test.ts
│ │ ├── mcp-readme-tools.test.ts
│ │ ├── memory-mcp-tools.test.ts
│ │ ├── readme-technical-writer.test.ts
│ │ └── workflow.test.ts
│ ├── memory
│ │ ├── contextual-retrieval.test.ts
│ │ ├── enhanced-manager.test.ts
│ │ ├── export-import.test.ts
│ │ ├── freshness-kg-integration.test.ts
│ │ ├── kg-code-integration.test.ts
│ │ ├── kg-health.test.ts
│ │ ├── kg-link-validator.test.ts
│ │ ├── kg-storage-validation.test.ts
│ │ ├── kg-storage.test.ts
│ │ ├── knowledge-graph-documentation-examples.test.ts
│ │ ├── knowledge-graph-enhanced.test.ts
│ │ ├── knowledge-graph.test.ts
│ │ ├── learning.test.ts
│ │ ├── manager-advanced.test.ts
│ │ ├── manager.test.ts
│ │ ├── mcp-resource-integration.test.ts
│ │ ├── mcp-tool-persistence.test.ts
│ │ ├── schemas-documentation-examples.test.ts
│ │ ├── schemas.test.ts
│ │ ├── storage.test.ts
│ │ ├── temporal-analysis.test.ts
│ │ └── user-preferences.test.ts
│ ├── performance
│ │ ├── memory-load-testing.test.ts
│ │ └── memory-stress-testing.test.ts
│ ├── prompts
│ │ ├── guided-workflow-prompts.test.ts
│ │ └── technical-writer-prompts.test.ts
│ ├── server.test.ts
│ ├── setup.ts
│ ├── tools
│ │ ├── all-tools.test.ts
│ │ ├── analyze-coverage.test.ts
│ │ ├── analyze-deployments.test.ts
│ │ ├── analyze-readme.test.ts
│ │ ├── analyze-repository.test.ts
│ │ ├── check-documentation-links.test.ts
│ │ ├── cleanup-agent-artifacts.test.ts
│ │ ├── deploy-pages-kg-retrieval.test.ts
│ │ ├── deploy-pages-tracking.test.ts
│ │ ├── deploy-pages.test.ts
│ │ ├── detect-gaps.test.ts
│ │ ├── evaluate-readme-health.test.ts
│ │ ├── generate-contextual-content.test.ts
│ │ ├── generate-llm-context.test.ts
│ │ ├── generate-readme-template.test.ts
│ │ ├── generate-technical-writer-prompts.test.ts
│ │ ├── kg-health-check.test.ts
│ │ ├── manage-sitemap.test.ts
│ │ ├── optimize-readme.test.ts
│ │ ├── readme-best-practices.test.ts
│ │ ├── recommend-ssg-historical.test.ts
│ │ ├── recommend-ssg-preferences.test.ts
│ │ ├── recommend-ssg.test.ts
│ │ ├── simple-coverage.test.ts
│ │ ├── sync-code-to-docs.test.ts
│ │ ├── test-local-deployment.test.ts
│ │ ├── tool-error-handling.test.ts
│ │ ├── track-documentation-freshness.test.ts
│ │ ├── validate-content.test.ts
│ │ ├── validate-documentation-freshness.test.ts
│ │ └── validate-readme-checklist.test.ts
│ ├── types
│ │ └── type-safety.test.ts
│ └── utils
│ ├── artifact-detector.test.ts
│ ├── ast-analyzer.test.ts
│ ├── content-extractor.test.ts
│ ├── drift-detector-diataxis.test.ts
│ ├── drift-detector-priority.test.ts
│ ├── drift-detector.test.ts
│ ├── freshness-tracker.test.ts
│ ├── llm-client.test.ts
│ ├── semantic-analyzer.test.ts
│ ├── sitemap-generator.test.ts
│ ├── usage-metadata.test.ts
│ └── user-feedback-integration.test.ts
├── tsconfig.json
└── typedoc.json
```
# Files
--------------------------------------------------------------------------------
/docs/api/assets/main.js:
--------------------------------------------------------------------------------
```javascript
"use strict";
window.translations = {
copy: "Copy",
copied: "Copied!",
normally_hidden:
"This member is normally hidden due to your filter settings.",
hierarchy_expand: "Expand",
hierarchy_collapse: "Collapse",
folder: "Folder",
search_index_not_available: "The search index is not available",
search_no_results_found_for_0: "No results found for {0}",
kind_1: "Project",
kind_2: "Module",
kind_4: "Namespace",
kind_8: "Enumeration",
kind_16: "Enumeration Member",
kind_32: "Variable",
kind_64: "Function",
kind_128: "Class",
kind_256: "Interface",
kind_512: "Constructor",
kind_1024: "Property",
kind_2048: "Method",
kind_4096: "Call Signature",
kind_8192: "Index Signature",
kind_16384: "Constructor Signature",
kind_32768: "Parameter",
kind_65536: "Type Literal",
kind_131072: "Type Parameter",
kind_262144: "Accessor",
kind_524288: "Get Signature",
kind_1048576: "Set Signature",
kind_2097152: "Type Alias",
kind_4194304: "Reference",
kind_8388608: "Document",
};
("use strict");
(() => {
var Ke = Object.create;
var he = Object.defineProperty;
var Ge = Object.getOwnPropertyDescriptor;
var Ze = Object.getOwnPropertyNames;
var Xe = Object.getPrototypeOf,
Ye = Object.prototype.hasOwnProperty;
var et = (t, e) => () => (
e || t((e = { exports: {} }).exports, e), e.exports
);
var tt = (t, e, n, r) => {
if ((e && typeof e == "object") || typeof e == "function")
for (let i of Ze(e))
!Ye.call(t, i) &&
i !== n &&
he(t, i, {
get: () => e[i],
enumerable: !(r = Ge(e, i)) || r.enumerable,
});
return t;
};
var nt = (t, e, n) => (
(n = t != null ? Ke(Xe(t)) : {}),
tt(
e || !t || !t.__esModule
? he(n, "default", { value: t, enumerable: !0 })
: n,
t,
)
);
var ye = et((me, ge) => {
(function () {
var t = function (e) {
var n = new t.Builder();
return (
n.pipeline.add(t.trimmer, t.stopWordFilter, t.stemmer),
n.searchPipeline.add(t.stemmer),
e.call(n, n),
n.build()
);
};
t.version = "2.3.9";
(t.utils = {}),
(t.utils.warn = (function (e) {
return function (n) {
e.console && console.warn && console.warn(n);
};
})(this)),
(t.utils.asString = function (e) {
return e == null ? "" : e.toString();
}),
(t.utils.clone = function (e) {
if (e == null) return e;
for (
var n = Object.create(null), r = Object.keys(e), i = 0;
i < r.length;
i++
) {
var s = r[i],
o = e[s];
if (Array.isArray(o)) {
n[s] = o.slice();
continue;
}
if (
typeof o == "string" ||
typeof o == "number" ||
typeof o == "boolean"
) {
n[s] = o;
continue;
}
throw new TypeError(
"clone is not deep and does not support nested objects",
);
}
return n;
}),
(t.FieldRef = function (e, n, r) {
(this.docRef = e), (this.fieldName = n), (this._stringValue = r);
}),
(t.FieldRef.joiner = "/"),
(t.FieldRef.fromString = function (e) {
var n = e.indexOf(t.FieldRef.joiner);
if (n === -1) throw "malformed field ref string";
var r = e.slice(0, n),
i = e.slice(n + 1);
return new t.FieldRef(i, r, e);
}),
(t.FieldRef.prototype.toString = function () {
return (
this._stringValue == null &&
(this._stringValue =
this.fieldName + t.FieldRef.joiner + this.docRef),
this._stringValue
);
});
(t.Set = function (e) {
if (((this.elements = Object.create(null)), e)) {
this.length = e.length;
for (var n = 0; n < this.length; n++) this.elements[e[n]] = !0;
} else this.length = 0;
}),
(t.Set.complete = {
intersect: function (e) {
return e;
},
union: function () {
return this;
},
contains: function () {
return !0;
},
}),
(t.Set.empty = {
intersect: function () {
return this;
},
union: function (e) {
return e;
},
contains: function () {
return !1;
},
}),
(t.Set.prototype.contains = function (e) {
return !!this.elements[e];
}),
(t.Set.prototype.intersect = function (e) {
var n,
r,
i,
s = [];
if (e === t.Set.complete) return this;
if (e === t.Set.empty) return e;
this.length < e.length
? ((n = this), (r = e))
: ((n = e), (r = this)),
(i = Object.keys(n.elements));
for (var o = 0; o < i.length; o++) {
var a = i[o];
a in r.elements && s.push(a);
}
return new t.Set(s);
}),
(t.Set.prototype.union = function (e) {
return e === t.Set.complete
? t.Set.complete
: e === t.Set.empty
? this
: new t.Set(
Object.keys(this.elements).concat(Object.keys(e.elements)),
);
}),
(t.idf = function (e, n) {
var r = 0;
for (var i in e) i != "_index" && (r += Object.keys(e[i]).length);
var s = (n - r + 0.5) / (r + 0.5);
return Math.log(1 + Math.abs(s));
}),
(t.Token = function (e, n) {
(this.str = e || ""), (this.metadata = n || {});
}),
(t.Token.prototype.toString = function () {
return this.str;
}),
(t.Token.prototype.update = function (e) {
return (this.str = e(this.str, this.metadata)), this;
}),
(t.Token.prototype.clone = function (e) {
return (
(e =
e ||
function (n) {
return n;
}),
new t.Token(e(this.str, this.metadata), this.metadata)
);
});
(t.tokenizer = function (e, n) {
if (e == null || e == null) return [];
if (Array.isArray(e))
return e.map(function (f) {
return new t.Token(
t.utils.asString(f).toLowerCase(),
t.utils.clone(n),
);
});
for (
var r = e.toString().toLowerCase(),
i = r.length,
s = [],
o = 0,
a = 0;
o <= i;
o++
) {
var c = r.charAt(o),
l = o - a;
if (c.match(t.tokenizer.separator) || o == i) {
if (l > 0) {
var d = t.utils.clone(n) || {};
(d.position = [a, l]),
(d.index = s.length),
s.push(new t.Token(r.slice(a, o), d));
}
a = o + 1;
}
}
return s;
}),
(t.tokenizer.separator = /[\s\-]+/);
(t.Pipeline = function () {
this._stack = [];
}),
(t.Pipeline.registeredFunctions = Object.create(null)),
(t.Pipeline.registerFunction = function (e, n) {
n in this.registeredFunctions &&
t.utils.warn("Overwriting existing registered function: " + n),
(e.label = n),
(t.Pipeline.registeredFunctions[e.label] = e);
}),
(t.Pipeline.warnIfFunctionNotRegistered = function (e) {
var n = e.label && e.label in this.registeredFunctions;
n ||
t.utils.warn(
`Function is not registered with pipeline. This may cause problems when serialising the index.
`,
e,
);
}),
(t.Pipeline.load = function (e) {
var n = new t.Pipeline();
return (
e.forEach(function (r) {
var i = t.Pipeline.registeredFunctions[r];
if (i) n.add(i);
else throw new Error("Cannot load unregistered function: " + r);
}),
n
);
}),
(t.Pipeline.prototype.add = function () {
var e = Array.prototype.slice.call(arguments);
e.forEach(function (n) {
t.Pipeline.warnIfFunctionNotRegistered(n), this._stack.push(n);
}, this);
}),
(t.Pipeline.prototype.after = function (e, n) {
t.Pipeline.warnIfFunctionNotRegistered(n);
var r = this._stack.indexOf(e);
if (r == -1) throw new Error("Cannot find existingFn");
(r = r + 1), this._stack.splice(r, 0, n);
}),
(t.Pipeline.prototype.before = function (e, n) {
t.Pipeline.warnIfFunctionNotRegistered(n);
var r = this._stack.indexOf(e);
if (r == -1) throw new Error("Cannot find existingFn");
this._stack.splice(r, 0, n);
}),
(t.Pipeline.prototype.remove = function (e) {
var n = this._stack.indexOf(e);
n != -1 && this._stack.splice(n, 1);
}),
(t.Pipeline.prototype.run = function (e) {
for (var n = this._stack.length, r = 0; r < n; r++) {
for (var i = this._stack[r], s = [], o = 0; o < e.length; o++) {
var a = i(e[o], o, e);
if (!(a == null || a === ""))
if (Array.isArray(a))
for (var c = 0; c < a.length; c++) s.push(a[c]);
else s.push(a);
}
e = s;
}
return e;
}),
(t.Pipeline.prototype.runString = function (e, n) {
var r = new t.Token(e, n);
return this.run([r]).map(function (i) {
return i.toString();
});
}),
(t.Pipeline.prototype.reset = function () {
this._stack = [];
}),
(t.Pipeline.prototype.toJSON = function () {
return this._stack.map(function (e) {
return t.Pipeline.warnIfFunctionNotRegistered(e), e.label;
});
});
(t.Vector = function (e) {
(this._magnitude = 0), (this.elements = e || []);
}),
(t.Vector.prototype.positionForIndex = function (e) {
if (this.elements.length == 0) return 0;
for (
var n = 0,
r = this.elements.length / 2,
i = r - n,
s = Math.floor(i / 2),
o = this.elements[s * 2];
i > 1 && (o < e && (n = s), o > e && (r = s), o != e);
)
(i = r - n),
(s = n + Math.floor(i / 2)),
(o = this.elements[s * 2]);
if (o == e || o > e) return s * 2;
if (o < e) return (s + 1) * 2;
}),
(t.Vector.prototype.insert = function (e, n) {
this.upsert(e, n, function () {
throw "duplicate index";
});
}),
(t.Vector.prototype.upsert = function (e, n, r) {
this._magnitude = 0;
var i = this.positionForIndex(e);
this.elements[i] == e
? (this.elements[i + 1] = r(this.elements[i + 1], n))
: this.elements.splice(i, 0, e, n);
}),
(t.Vector.prototype.magnitude = function () {
if (this._magnitude) return this._magnitude;
for (var e = 0, n = this.elements.length, r = 1; r < n; r += 2) {
var i = this.elements[r];
e += i * i;
}
return (this._magnitude = Math.sqrt(e));
}),
(t.Vector.prototype.dot = function (e) {
for (
var n = 0,
r = this.elements,
i = e.elements,
s = r.length,
o = i.length,
a = 0,
c = 0,
l = 0,
d = 0;
l < s && d < o;
)
(a = r[l]),
(c = i[d]),
a < c
? (l += 2)
: a > c
? (d += 2)
: a == c && ((n += r[l + 1] * i[d + 1]), (l += 2), (d += 2));
return n;
}),
(t.Vector.prototype.similarity = function (e) {
return this.dot(e) / this.magnitude() || 0;
}),
(t.Vector.prototype.toArray = function () {
for (
var e = new Array(this.elements.length / 2), n = 1, r = 0;
n < this.elements.length;
n += 2, r++
)
e[r] = this.elements[n];
return e;
}),
(t.Vector.prototype.toJSON = function () {
return this.elements;
});
(t.stemmer = (function () {
var e = {
ational: "ate",
tional: "tion",
enci: "ence",
anci: "ance",
izer: "ize",
bli: "ble",
alli: "al",
entli: "ent",
eli: "e",
ousli: "ous",
ization: "ize",
ation: "ate",
ator: "ate",
alism: "al",
iveness: "ive",
fulness: "ful",
ousness: "ous",
aliti: "al",
iviti: "ive",
biliti: "ble",
logi: "log",
},
n = {
icate: "ic",
ative: "",
alize: "al",
iciti: "ic",
ical: "ic",
ful: "",
ness: "",
},
r = "[^aeiou]",
i = "[aeiouy]",
s = r + "[^aeiouy]*",
o = i + "[aeiou]*",
a = "^(" + s + ")?" + o + s,
c = "^(" + s + ")?" + o + s + "(" + o + ")?$",
l = "^(" + s + ")?" + o + s + o + s,
d = "^(" + s + ")?" + i,
f = new RegExp(a),
p = new RegExp(l),
v = new RegExp(c),
x = new RegExp(d),
w = /^(.+?)(ss|i)es$/,
m = /^(.+?)([^s])s$/,
g = /^(.+?)eed$/,
T = /^(.+?)(ed|ing)$/,
L = /.$/,
C = /(at|bl|iz)$/,
O = new RegExp("([^aeiouylsz])\\1$"),
j = new RegExp("^" + s + i + "[^aeiouwxy]$"),
N = /^(.+?[^aeiou])y$/,
q =
/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,
W = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,
B =
/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,
z = /^(.+?)(s|t)(ion)$/,
_ = /^(.+?)e$/,
U = /ll$/,
J = new RegExp("^" + s + i + "[^aeiouwxy]$"),
V = function (u) {
var y, P, k, h, E, Q, H;
if (u.length < 3) return u;
if (
((k = u.substr(0, 1)),
k == "y" && (u = k.toUpperCase() + u.substr(1)),
(h = w),
(E = m),
h.test(u)
? (u = u.replace(h, "$1$2"))
: E.test(u) && (u = u.replace(E, "$1$2")),
(h = g),
(E = T),
h.test(u))
) {
var b = h.exec(u);
(h = f), h.test(b[1]) && ((h = L), (u = u.replace(h, "")));
} else if (E.test(u)) {
var b = E.exec(u);
(y = b[1]),
(E = x),
E.test(y) &&
((u = y),
(E = C),
(Q = O),
(H = j),
E.test(u)
? (u = u + "e")
: Q.test(u)
? ((h = L), (u = u.replace(h, "")))
: H.test(u) && (u = u + "e"));
}
if (((h = N), h.test(u))) {
var b = h.exec(u);
(y = b[1]), (u = y + "i");
}
if (((h = q), h.test(u))) {
var b = h.exec(u);
(y = b[1]), (P = b[2]), (h = f), h.test(y) && (u = y + e[P]);
}
if (((h = W), h.test(u))) {
var b = h.exec(u);
(y = b[1]), (P = b[2]), (h = f), h.test(y) && (u = y + n[P]);
}
if (((h = B), (E = z), h.test(u))) {
var b = h.exec(u);
(y = b[1]), (h = p), h.test(y) && (u = y);
} else if (E.test(u)) {
var b = E.exec(u);
(y = b[1] + b[2]), (E = p), E.test(y) && (u = y);
}
if (((h = _), h.test(u))) {
var b = h.exec(u);
(y = b[1]),
(h = p),
(E = v),
(Q = J),
(h.test(y) || (E.test(y) && !Q.test(y))) && (u = y);
}
return (
(h = U),
(E = p),
h.test(u) && E.test(u) && ((h = L), (u = u.replace(h, ""))),
k == "y" && (u = k.toLowerCase() + u.substr(1)),
u
);
};
return function (A) {
return A.update(V);
};
})()),
t.Pipeline.registerFunction(t.stemmer, "stemmer");
(t.generateStopWordFilter = function (e) {
var n = e.reduce(function (r, i) {
return (r[i] = i), r;
}, {});
return function (r) {
if (r && n[r.toString()] !== r.toString()) return r;
};
}),
(t.stopWordFilter = t.generateStopWordFilter([
"a",
"able",
"about",
"across",
"after",
"all",
"almost",
"also",
"am",
"among",
"an",
"and",
"any",
"are",
"as",
"at",
"be",
"because",
"been",
"but",
"by",
"can",
"cannot",
"could",
"dear",
"did",
"do",
"does",
"either",
"else",
"ever",
"every",
"for",
"from",
"get",
"got",
"had",
"has",
"have",
"he",
"her",
"hers",
"him",
"his",
"how",
"however",
"i",
"if",
"in",
"into",
"is",
"it",
"its",
"just",
"least",
"let",
"like",
"likely",
"may",
"me",
"might",
"most",
"must",
"my",
"neither",
"no",
"nor",
"not",
"of",
"off",
"often",
"on",
"only",
"or",
"other",
"our",
"own",
"rather",
"said",
"say",
"says",
"she",
"should",
"since",
"so",
"some",
"than",
"that",
"the",
"their",
"them",
"then",
"there",
"these",
"they",
"this",
"tis",
"to",
"too",
"twas",
"us",
"wants",
"was",
"we",
"were",
"what",
"when",
"where",
"which",
"while",
"who",
"whom",
"why",
"will",
"with",
"would",
"yet",
"you",
"your",
])),
t.Pipeline.registerFunction(t.stopWordFilter, "stopWordFilter");
(t.trimmer = function (e) {
return e.update(function (n) {
return n.replace(/^\W+/, "").replace(/\W+$/, "");
});
}),
t.Pipeline.registerFunction(t.trimmer, "trimmer");
(t.TokenSet = function () {
(this.final = !1),
(this.edges = {}),
(this.id = t.TokenSet._nextId),
(t.TokenSet._nextId += 1);
}),
(t.TokenSet._nextId = 1),
(t.TokenSet.fromArray = function (e) {
for (
var n = new t.TokenSet.Builder(), r = 0, i = e.length;
r < i;
r++
)
n.insert(e[r]);
return n.finish(), n.root;
}),
(t.TokenSet.fromClause = function (e) {
return "editDistance" in e
? t.TokenSet.fromFuzzyString(e.term, e.editDistance)
: t.TokenSet.fromString(e.term);
}),
(t.TokenSet.fromFuzzyString = function (e, n) {
for (
var r = new t.TokenSet(),
i = [{ node: r, editsRemaining: n, str: e }];
i.length;
) {
var s = i.pop();
if (s.str.length > 0) {
var o = s.str.charAt(0),
a;
o in s.node.edges
? (a = s.node.edges[o])
: ((a = new t.TokenSet()), (s.node.edges[o] = a)),
s.str.length == 1 && (a.final = !0),
i.push({
node: a,
editsRemaining: s.editsRemaining,
str: s.str.slice(1),
});
}
if (s.editsRemaining != 0) {
if ("*" in s.node.edges) var c = s.node.edges["*"];
else {
var c = new t.TokenSet();
s.node.edges["*"] = c;
}
if (
(s.str.length == 0 && (c.final = !0),
i.push({
node: c,
editsRemaining: s.editsRemaining - 1,
str: s.str,
}),
s.str.length > 1 &&
i.push({
node: s.node,
editsRemaining: s.editsRemaining - 1,
str: s.str.slice(1),
}),
s.str.length == 1 && (s.node.final = !0),
s.str.length >= 1)
) {
if ("*" in s.node.edges) var l = s.node.edges["*"];
else {
var l = new t.TokenSet();
s.node.edges["*"] = l;
}
s.str.length == 1 && (l.final = !0),
i.push({
node: l,
editsRemaining: s.editsRemaining - 1,
str: s.str.slice(1),
});
}
if (s.str.length > 1) {
var d = s.str.charAt(0),
f = s.str.charAt(1),
p;
f in s.node.edges
? (p = s.node.edges[f])
: ((p = new t.TokenSet()), (s.node.edges[f] = p)),
s.str.length == 1 && (p.final = !0),
i.push({
node: p,
editsRemaining: s.editsRemaining - 1,
str: d + s.str.slice(2),
});
}
}
}
return r;
}),
(t.TokenSet.fromString = function (e) {
for (
var n = new t.TokenSet(), r = n, i = 0, s = e.length;
i < s;
i++
) {
var o = e[i],
a = i == s - 1;
if (o == "*") (n.edges[o] = n), (n.final = a);
else {
var c = new t.TokenSet();
(c.final = a), (n.edges[o] = c), (n = c);
}
}
return r;
}),
(t.TokenSet.prototype.toArray = function () {
for (var e = [], n = [{ prefix: "", node: this }]; n.length; ) {
var r = n.pop(),
i = Object.keys(r.node.edges),
s = i.length;
r.node.final && (r.prefix.charAt(0), e.push(r.prefix));
for (var o = 0; o < s; o++) {
var a = i[o];
n.push({ prefix: r.prefix.concat(a), node: r.node.edges[a] });
}
}
return e;
}),
(t.TokenSet.prototype.toString = function () {
if (this._str) return this._str;
for (
var e = this.final ? "1" : "0",
n = Object.keys(this.edges).sort(),
r = n.length,
i = 0;
i < r;
i++
) {
var s = n[i],
o = this.edges[s];
e = e + s + o.id;
}
return e;
}),
(t.TokenSet.prototype.intersect = function (e) {
for (
var n = new t.TokenSet(),
r = void 0,
i = [{ qNode: e, output: n, node: this }];
i.length;
) {
r = i.pop();
for (
var s = Object.keys(r.qNode.edges),
o = s.length,
a = Object.keys(r.node.edges),
c = a.length,
l = 0;
l < o;
l++
)
for (var d = s[l], f = 0; f < c; f++) {
var p = a[f];
if (p == d || d == "*") {
var v = r.node.edges[p],
x = r.qNode.edges[d],
w = v.final && x.final,
m = void 0;
p in r.output.edges
? ((m = r.output.edges[p]), (m.final = m.final || w))
: ((m = new t.TokenSet()),
(m.final = w),
(r.output.edges[p] = m)),
i.push({ qNode: x, output: m, node: v });
}
}
}
return n;
}),
(t.TokenSet.Builder = function () {
(this.previousWord = ""),
(this.root = new t.TokenSet()),
(this.uncheckedNodes = []),
(this.minimizedNodes = {});
}),
(t.TokenSet.Builder.prototype.insert = function (e) {
var n,
r = 0;
if (e < this.previousWord)
throw new Error("Out of order word insertion");
for (
var i = 0;
i < e.length &&
i < this.previousWord.length &&
e[i] == this.previousWord[i];
i++
)
r++;
this.minimize(r),
this.uncheckedNodes.length == 0
? (n = this.root)
: (n = this.uncheckedNodes[this.uncheckedNodes.length - 1].child);
for (var i = r; i < e.length; i++) {
var s = new t.TokenSet(),
o = e[i];
(n.edges[o] = s),
this.uncheckedNodes.push({ parent: n, char: o, child: s }),
(n = s);
}
(n.final = !0), (this.previousWord = e);
}),
(t.TokenSet.Builder.prototype.finish = function () {
this.minimize(0);
}),
(t.TokenSet.Builder.prototype.minimize = function (e) {
for (var n = this.uncheckedNodes.length - 1; n >= e; n--) {
var r = this.uncheckedNodes[n],
i = r.child.toString();
i in this.minimizedNodes
? (r.parent.edges[r.char] = this.minimizedNodes[i])
: ((r.child._str = i), (this.minimizedNodes[i] = r.child)),
this.uncheckedNodes.pop();
}
});
(t.Index = function (e) {
(this.invertedIndex = e.invertedIndex),
(this.fieldVectors = e.fieldVectors),
(this.tokenSet = e.tokenSet),
(this.fields = e.fields),
(this.pipeline = e.pipeline);
}),
(t.Index.prototype.search = function (e) {
return this.query(function (n) {
var r = new t.QueryParser(e, n);
r.parse();
});
}),
(t.Index.prototype.query = function (e) {
for (
var n = new t.Query(this.fields),
r = Object.create(null),
i = Object.create(null),
s = Object.create(null),
o = Object.create(null),
a = Object.create(null),
c = 0;
c < this.fields.length;
c++
)
i[this.fields[c]] = new t.Vector();
e.call(n, n);
for (var c = 0; c < n.clauses.length; c++) {
var l = n.clauses[c],
d = null,
f = t.Set.empty;
l.usePipeline
? (d = this.pipeline.runString(l.term, { fields: l.fields }))
: (d = [l.term]);
for (var p = 0; p < d.length; p++) {
var v = d[p];
l.term = v;
var x = t.TokenSet.fromClause(l),
w = this.tokenSet.intersect(x).toArray();
if (w.length === 0 && l.presence === t.Query.presence.REQUIRED) {
for (var m = 0; m < l.fields.length; m++) {
var g = l.fields[m];
o[g] = t.Set.empty;
}
break;
}
for (var T = 0; T < w.length; T++)
for (
var L = w[T], C = this.invertedIndex[L], O = C._index, m = 0;
m < l.fields.length;
m++
) {
var g = l.fields[m],
j = C[g],
N = Object.keys(j),
q = L + "/" + g,
W = new t.Set(N);
if (
(l.presence == t.Query.presence.REQUIRED &&
((f = f.union(W)),
o[g] === void 0 && (o[g] = t.Set.complete)),
l.presence == t.Query.presence.PROHIBITED)
) {
a[g] === void 0 && (a[g] = t.Set.empty),
(a[g] = a[g].union(W));
continue;
}
if (
(i[g].upsert(O, l.boost, function (Ue, Je) {
return Ue + Je;
}),
!s[q])
) {
for (var B = 0; B < N.length; B++) {
var z = N[B],
_ = new t.FieldRef(z, g),
U = j[z],
J;
(J = r[_]) === void 0
? (r[_] = new t.MatchData(L, g, U))
: J.add(L, g, U);
}
s[q] = !0;
}
}
}
if (l.presence === t.Query.presence.REQUIRED)
for (var m = 0; m < l.fields.length; m++) {
var g = l.fields[m];
o[g] = o[g].intersect(f);
}
}
for (
var V = t.Set.complete, A = t.Set.empty, c = 0;
c < this.fields.length;
c++
) {
var g = this.fields[c];
o[g] && (V = V.intersect(o[g])), a[g] && (A = A.union(a[g]));
}
var u = Object.keys(r),
y = [],
P = Object.create(null);
if (n.isNegated()) {
u = Object.keys(this.fieldVectors);
for (var c = 0; c < u.length; c++) {
var _ = u[c],
k = t.FieldRef.fromString(_);
r[_] = new t.MatchData();
}
}
for (var c = 0; c < u.length; c++) {
var k = t.FieldRef.fromString(u[c]),
h = k.docRef;
if (V.contains(h) && !A.contains(h)) {
var E = this.fieldVectors[k],
Q = i[k.fieldName].similarity(E),
H;
if ((H = P[h]) !== void 0)
(H.score += Q), H.matchData.combine(r[k]);
else {
var b = { ref: h, score: Q, matchData: r[k] };
(P[h] = b), y.push(b);
}
}
}
return y.sort(function (We, ze) {
return ze.score - We.score;
});
}),
(t.Index.prototype.toJSON = function () {
var e = Object.keys(this.invertedIndex)
.sort()
.map(function (r) {
return [r, this.invertedIndex[r]];
}, this),
n = Object.keys(this.fieldVectors).map(function (r) {
return [r, this.fieldVectors[r].toJSON()];
}, this);
return {
version: t.version,
fields: this.fields,
fieldVectors: n,
invertedIndex: e,
pipeline: this.pipeline.toJSON(),
};
}),
(t.Index.load = function (e) {
var n = {},
r = {},
i = e.fieldVectors,
s = Object.create(null),
o = e.invertedIndex,
a = new t.TokenSet.Builder(),
c = t.Pipeline.load(e.pipeline);
e.version != t.version &&
t.utils.warn(
"Version mismatch when loading serialised index. Current version of lunr '" +
t.version +
"' does not match serialized index '" +
e.version +
"'",
);
for (var l = 0; l < i.length; l++) {
var d = i[l],
f = d[0],
p = d[1];
r[f] = new t.Vector(p);
}
for (var l = 0; l < o.length; l++) {
var d = o[l],
v = d[0],
x = d[1];
a.insert(v), (s[v] = x);
}
return (
a.finish(),
(n.fields = e.fields),
(n.fieldVectors = r),
(n.invertedIndex = s),
(n.tokenSet = a.root),
(n.pipeline = c),
new t.Index(n)
);
});
(t.Builder = function () {
(this._ref = "id"),
(this._fields = Object.create(null)),
(this._documents = Object.create(null)),
(this.invertedIndex = Object.create(null)),
(this.fieldTermFrequencies = {}),
(this.fieldLengths = {}),
(this.tokenizer = t.tokenizer),
(this.pipeline = new t.Pipeline()),
(this.searchPipeline = new t.Pipeline()),
(this.documentCount = 0),
(this._b = 0.75),
(this._k1 = 1.2),
(this.termIndex = 0),
(this.metadataWhitelist = []);
}),
(t.Builder.prototype.ref = function (e) {
this._ref = e;
}),
(t.Builder.prototype.field = function (e, n) {
if (/\//.test(e))
throw new RangeError(
"Field '" + e + "' contains illegal character '/'",
);
this._fields[e] = n || {};
}),
(t.Builder.prototype.b = function (e) {
e < 0 ? (this._b = 0) : e > 1 ? (this._b = 1) : (this._b = e);
}),
(t.Builder.prototype.k1 = function (e) {
this._k1 = e;
}),
(t.Builder.prototype.add = function (e, n) {
var r = e[this._ref],
i = Object.keys(this._fields);
(this._documents[r] = n || {}), (this.documentCount += 1);
for (var s = 0; s < i.length; s++) {
var o = i[s],
a = this._fields[o].extractor,
c = a ? a(e) : e[o],
l = this.tokenizer(c, { fields: [o] }),
d = this.pipeline.run(l),
f = new t.FieldRef(r, o),
p = Object.create(null);
(this.fieldTermFrequencies[f] = p),
(this.fieldLengths[f] = 0),
(this.fieldLengths[f] += d.length);
for (var v = 0; v < d.length; v++) {
var x = d[v];
if (
(p[x] == null && (p[x] = 0),
(p[x] += 1),
this.invertedIndex[x] == null)
) {
var w = Object.create(null);
(w._index = this.termIndex), (this.termIndex += 1);
for (var m = 0; m < i.length; m++)
w[i[m]] = Object.create(null);
this.invertedIndex[x] = w;
}
this.invertedIndex[x][o][r] == null &&
(this.invertedIndex[x][o][r] = Object.create(null));
for (var g = 0; g < this.metadataWhitelist.length; g++) {
var T = this.metadataWhitelist[g],
L = x.metadata[T];
this.invertedIndex[x][o][r][T] == null &&
(this.invertedIndex[x][o][r][T] = []),
this.invertedIndex[x][o][r][T].push(L);
}
}
}
}),
(t.Builder.prototype.calculateAverageFieldLengths = function () {
for (
var e = Object.keys(this.fieldLengths),
n = e.length,
r = {},
i = {},
s = 0;
s < n;
s++
) {
var o = t.FieldRef.fromString(e[s]),
a = o.fieldName;
i[a] || (i[a] = 0),
(i[a] += 1),
r[a] || (r[a] = 0),
(r[a] += this.fieldLengths[o]);
}
for (var c = Object.keys(this._fields), s = 0; s < c.length; s++) {
var l = c[s];
r[l] = r[l] / i[l];
}
this.averageFieldLength = r;
}),
(t.Builder.prototype.createFieldVectors = function () {
for (
var e = {},
n = Object.keys(this.fieldTermFrequencies),
r = n.length,
i = Object.create(null),
s = 0;
s < r;
s++
) {
for (
var o = t.FieldRef.fromString(n[s]),
a = o.fieldName,
c = this.fieldLengths[o],
l = new t.Vector(),
d = this.fieldTermFrequencies[o],
f = Object.keys(d),
p = f.length,
v = this._fields[a].boost || 1,
x = this._documents[o.docRef].boost || 1,
w = 0;
w < p;
w++
) {
var m = f[w],
g = d[m],
T = this.invertedIndex[m]._index,
L,
C,
O;
i[m] === void 0
? ((L = t.idf(this.invertedIndex[m], this.documentCount)),
(i[m] = L))
: (L = i[m]),
(C =
(L * ((this._k1 + 1) * g)) /
(this._k1 *
(1 - this._b + this._b * (c / this.averageFieldLength[a])) +
g)),
(C *= v),
(C *= x),
(O = Math.round(C * 1e3) / 1e3),
l.insert(T, O);
}
e[o] = l;
}
this.fieldVectors = e;
}),
(t.Builder.prototype.createTokenSet = function () {
this.tokenSet = t.TokenSet.fromArray(
Object.keys(this.invertedIndex).sort(),
);
}),
(t.Builder.prototype.build = function () {
return (
this.calculateAverageFieldLengths(),
this.createFieldVectors(),
this.createTokenSet(),
new t.Index({
invertedIndex: this.invertedIndex,
fieldVectors: this.fieldVectors,
tokenSet: this.tokenSet,
fields: Object.keys(this._fields),
pipeline: this.searchPipeline,
})
);
}),
(t.Builder.prototype.use = function (e) {
var n = Array.prototype.slice.call(arguments, 1);
n.unshift(this), e.apply(this, n);
}),
(t.MatchData = function (e, n, r) {
for (
var i = Object.create(null), s = Object.keys(r || {}), o = 0;
o < s.length;
o++
) {
var a = s[o];
i[a] = r[a].slice();
}
(this.metadata = Object.create(null)),
e !== void 0 &&
((this.metadata[e] = Object.create(null)),
(this.metadata[e][n] = i));
}),
(t.MatchData.prototype.combine = function (e) {
for (var n = Object.keys(e.metadata), r = 0; r < n.length; r++) {
var i = n[r],
s = Object.keys(e.metadata[i]);
this.metadata[i] == null &&
(this.metadata[i] = Object.create(null));
for (var o = 0; o < s.length; o++) {
var a = s[o],
c = Object.keys(e.metadata[i][a]);
this.metadata[i][a] == null &&
(this.metadata[i][a] = Object.create(null));
for (var l = 0; l < c.length; l++) {
var d = c[l];
this.metadata[i][a][d] == null
? (this.metadata[i][a][d] = e.metadata[i][a][d])
: (this.metadata[i][a][d] = this.metadata[i][a][d].concat(
e.metadata[i][a][d],
));
}
}
}
}),
(t.MatchData.prototype.add = function (e, n, r) {
if (!(e in this.metadata)) {
(this.metadata[e] = Object.create(null)), (this.metadata[e][n] = r);
return;
}
if (!(n in this.metadata[e])) {
this.metadata[e][n] = r;
return;
}
for (var i = Object.keys(r), s = 0; s < i.length; s++) {
var o = i[s];
o in this.metadata[e][n]
? (this.metadata[e][n][o] = this.metadata[e][n][o].concat(r[o]))
: (this.metadata[e][n][o] = r[o]);
}
}),
(t.Query = function (e) {
(this.clauses = []), (this.allFields = e);
}),
(t.Query.wildcard = new String("*")),
(t.Query.wildcard.NONE = 0),
(t.Query.wildcard.LEADING = 1),
(t.Query.wildcard.TRAILING = 2),
(t.Query.presence = { OPTIONAL: 1, REQUIRED: 2, PROHIBITED: 3 }),
(t.Query.prototype.clause = function (e) {
return (
"fields" in e || (e.fields = this.allFields),
"boost" in e || (e.boost = 1),
"usePipeline" in e || (e.usePipeline = !0),
"wildcard" in e || (e.wildcard = t.Query.wildcard.NONE),
e.wildcard & t.Query.wildcard.LEADING &&
e.term.charAt(0) != t.Query.wildcard &&
(e.term = "*" + e.term),
e.wildcard & t.Query.wildcard.TRAILING &&
e.term.slice(-1) != t.Query.wildcard &&
(e.term = "" + e.term + "*"),
"presence" in e || (e.presence = t.Query.presence.OPTIONAL),
this.clauses.push(e),
this
);
}),
(t.Query.prototype.isNegated = function () {
for (var e = 0; e < this.clauses.length; e++)
if (this.clauses[e].presence != t.Query.presence.PROHIBITED)
return !1;
return !0;
}),
(t.Query.prototype.term = function (e, n) {
if (Array.isArray(e))
return (
e.forEach(function (i) {
this.term(i, t.utils.clone(n));
}, this),
this
);
var r = n || {};
return (r.term = e.toString()), this.clause(r), this;
}),
(t.QueryParseError = function (e, n, r) {
(this.name = "QueryParseError"),
(this.message = e),
(this.start = n),
(this.end = r);
}),
(t.QueryParseError.prototype = new Error()),
(t.QueryLexer = function (e) {
(this.lexemes = []),
(this.str = e),
(this.length = e.length),
(this.pos = 0),
(this.start = 0),
(this.escapeCharPositions = []);
}),
(t.QueryLexer.prototype.run = function () {
for (var e = t.QueryLexer.lexText; e; ) e = e(this);
}),
(t.QueryLexer.prototype.sliceString = function () {
for (
var e = [], n = this.start, r = this.pos, i = 0;
i < this.escapeCharPositions.length;
i++
)
(r = this.escapeCharPositions[i]),
e.push(this.str.slice(n, r)),
(n = r + 1);
return (
e.push(this.str.slice(n, this.pos)),
(this.escapeCharPositions.length = 0),
e.join("")
);
}),
(t.QueryLexer.prototype.emit = function (e) {
this.lexemes.push({
type: e,
str: this.sliceString(),
start: this.start,
end: this.pos,
}),
(this.start = this.pos);
}),
(t.QueryLexer.prototype.escapeCharacter = function () {
this.escapeCharPositions.push(this.pos - 1), (this.pos += 1);
}),
(t.QueryLexer.prototype.next = function () {
if (this.pos >= this.length) return t.QueryLexer.EOS;
var e = this.str.charAt(this.pos);
return (this.pos += 1), e;
}),
(t.QueryLexer.prototype.width = function () {
return this.pos - this.start;
}),
(t.QueryLexer.prototype.ignore = function () {
this.start == this.pos && (this.pos += 1), (this.start = this.pos);
}),
(t.QueryLexer.prototype.backup = function () {
this.pos -= 1;
}),
(t.QueryLexer.prototype.acceptDigitRun = function () {
var e, n;
do (e = this.next()), (n = e.charCodeAt(0));
while (n > 47 && n < 58);
e != t.QueryLexer.EOS && this.backup();
}),
(t.QueryLexer.prototype.more = function () {
return this.pos < this.length;
}),
(t.QueryLexer.EOS = "EOS"),
(t.QueryLexer.FIELD = "FIELD"),
(t.QueryLexer.TERM = "TERM"),
(t.QueryLexer.EDIT_DISTANCE = "EDIT_DISTANCE"),
(t.QueryLexer.BOOST = "BOOST"),
(t.QueryLexer.PRESENCE = "PRESENCE"),
(t.QueryLexer.lexField = function (e) {
return (
e.backup(),
e.emit(t.QueryLexer.FIELD),
e.ignore(),
t.QueryLexer.lexText
);
}),
(t.QueryLexer.lexTerm = function (e) {
if (
(e.width() > 1 && (e.backup(), e.emit(t.QueryLexer.TERM)),
e.ignore(),
e.more())
)
return t.QueryLexer.lexText;
}),
(t.QueryLexer.lexEditDistance = function (e) {
return (
e.ignore(),
e.acceptDigitRun(),
e.emit(t.QueryLexer.EDIT_DISTANCE),
t.QueryLexer.lexText
);
}),
(t.QueryLexer.lexBoost = function (e) {
return (
e.ignore(),
e.acceptDigitRun(),
e.emit(t.QueryLexer.BOOST),
t.QueryLexer.lexText
);
}),
(t.QueryLexer.lexEOS = function (e) {
e.width() > 0 && e.emit(t.QueryLexer.TERM);
}),
(t.QueryLexer.termSeparator = t.tokenizer.separator),
(t.QueryLexer.lexText = function (e) {
for (;;) {
var n = e.next();
if (n == t.QueryLexer.EOS) return t.QueryLexer.lexEOS;
if (n.charCodeAt(0) == 92) {
e.escapeCharacter();
continue;
}
if (n == ":") return t.QueryLexer.lexField;
if (n == "~")
return (
e.backup(),
e.width() > 0 && e.emit(t.QueryLexer.TERM),
t.QueryLexer.lexEditDistance
);
if (n == "^")
return (
e.backup(),
e.width() > 0 && e.emit(t.QueryLexer.TERM),
t.QueryLexer.lexBoost
);
if ((n == "+" && e.width() === 1) || (n == "-" && e.width() === 1))
return e.emit(t.QueryLexer.PRESENCE), t.QueryLexer.lexText;
if (n.match(t.QueryLexer.termSeparator))
return t.QueryLexer.lexTerm;
}
}),
(t.QueryParser = function (e, n) {
(this.lexer = new t.QueryLexer(e)),
(this.query = n),
(this.currentClause = {}),
(this.lexemeIdx = 0);
}),
(t.QueryParser.prototype.parse = function () {
this.lexer.run(), (this.lexemes = this.lexer.lexemes);
for (var e = t.QueryParser.parseClause; e; ) e = e(this);
return this.query;
}),
(t.QueryParser.prototype.peekLexeme = function () {
return this.lexemes[this.lexemeIdx];
}),
(t.QueryParser.prototype.consumeLexeme = function () {
var e = this.peekLexeme();
return (this.lexemeIdx += 1), e;
}),
(t.QueryParser.prototype.nextClause = function () {
var e = this.currentClause;
this.query.clause(e), (this.currentClause = {});
}),
(t.QueryParser.parseClause = function (e) {
var n = e.peekLexeme();
if (n != null)
switch (n.type) {
case t.QueryLexer.PRESENCE:
return t.QueryParser.parsePresence;
case t.QueryLexer.FIELD:
return t.QueryParser.parseField;
case t.QueryLexer.TERM:
return t.QueryParser.parseTerm;
default:
var r = "expected either a field or a term, found " + n.type;
throw (
(n.str.length >= 1 && (r += " with value '" + n.str + "'"),
new t.QueryParseError(r, n.start, n.end))
);
}
}),
(t.QueryParser.parsePresence = function (e) {
var n = e.consumeLexeme();
if (n != null) {
switch (n.str) {
case "-":
e.currentClause.presence = t.Query.presence.PROHIBITED;
break;
case "+":
e.currentClause.presence = t.Query.presence.REQUIRED;
break;
default:
var r = "unrecognised presence operator'" + n.str + "'";
throw new t.QueryParseError(r, n.start, n.end);
}
var i = e.peekLexeme();
if (i == null) {
var r = "expecting term or field, found nothing";
throw new t.QueryParseError(r, n.start, n.end);
}
switch (i.type) {
case t.QueryLexer.FIELD:
return t.QueryParser.parseField;
case t.QueryLexer.TERM:
return t.QueryParser.parseTerm;
default:
var r = "expecting term or field, found '" + i.type + "'";
throw new t.QueryParseError(r, i.start, i.end);
}
}
}),
(t.QueryParser.parseField = function (e) {
var n = e.consumeLexeme();
if (n != null) {
if (e.query.allFields.indexOf(n.str) == -1) {
var r = e.query.allFields
.map(function (o) {
return "'" + o + "'";
})
.join(", "),
i = "unrecognised field '" + n.str + "', possible fields: " + r;
throw new t.QueryParseError(i, n.start, n.end);
}
e.currentClause.fields = [n.str];
var s = e.peekLexeme();
if (s == null) {
var i = "expecting term, found nothing";
throw new t.QueryParseError(i, n.start, n.end);
}
switch (s.type) {
case t.QueryLexer.TERM:
return t.QueryParser.parseTerm;
default:
var i = "expecting term, found '" + s.type + "'";
throw new t.QueryParseError(i, s.start, s.end);
}
}
}),
(t.QueryParser.parseTerm = function (e) {
var n = e.consumeLexeme();
if (n != null) {
(e.currentClause.term = n.str.toLowerCase()),
n.str.indexOf("*") != -1 && (e.currentClause.usePipeline = !1);
var r = e.peekLexeme();
if (r == null) {
e.nextClause();
return;
}
switch (r.type) {
case t.QueryLexer.TERM:
return e.nextClause(), t.QueryParser.parseTerm;
case t.QueryLexer.FIELD:
return e.nextClause(), t.QueryParser.parseField;
case t.QueryLexer.EDIT_DISTANCE:
return t.QueryParser.parseEditDistance;
case t.QueryLexer.BOOST:
return t.QueryParser.parseBoost;
case t.QueryLexer.PRESENCE:
return e.nextClause(), t.QueryParser.parsePresence;
default:
var i = "Unexpected lexeme type '" + r.type + "'";
throw new t.QueryParseError(i, r.start, r.end);
}
}
}),
(t.QueryParser.parseEditDistance = function (e) {
var n = e.consumeLexeme();
if (n != null) {
var r = parseInt(n.str, 10);
if (isNaN(r)) {
var i = "edit distance must be numeric";
throw new t.QueryParseError(i, n.start, n.end);
}
e.currentClause.editDistance = r;
var s = e.peekLexeme();
if (s == null) {
e.nextClause();
return;
}
switch (s.type) {
case t.QueryLexer.TERM:
return e.nextClause(), t.QueryParser.parseTerm;
case t.QueryLexer.FIELD:
return e.nextClause(), t.QueryParser.parseField;
case t.QueryLexer.EDIT_DISTANCE:
return t.QueryParser.parseEditDistance;
case t.QueryLexer.BOOST:
return t.QueryParser.parseBoost;
case t.QueryLexer.PRESENCE:
return e.nextClause(), t.QueryParser.parsePresence;
default:
var i = "Unexpected lexeme type '" + s.type + "'";
throw new t.QueryParseError(i, s.start, s.end);
}
}
}),
(t.QueryParser.parseBoost = function (e) {
var n = e.consumeLexeme();
if (n != null) {
var r = parseInt(n.str, 10);
if (isNaN(r)) {
var i = "boost must be numeric";
throw new t.QueryParseError(i, n.start, n.end);
}
e.currentClause.boost = r;
var s = e.peekLexeme();
if (s == null) {
e.nextClause();
return;
}
switch (s.type) {
case t.QueryLexer.TERM:
return e.nextClause(), t.QueryParser.parseTerm;
case t.QueryLexer.FIELD:
return e.nextClause(), t.QueryParser.parseField;
case t.QueryLexer.EDIT_DISTANCE:
return t.QueryParser.parseEditDistance;
case t.QueryLexer.BOOST:
return t.QueryParser.parseBoost;
case t.QueryLexer.PRESENCE:
return e.nextClause(), t.QueryParser.parsePresence;
default:
var i = "Unexpected lexeme type '" + s.type + "'";
throw new t.QueryParseError(i, s.start, s.end);
}
}
}),
(function (e, n) {
typeof define == "function" && define.amd
? define(n)
: typeof me == "object"
? (ge.exports = n())
: (e.lunr = n());
})(this, function () {
return t;
});
})();
});
var M,
G = {
getItem() {
return null;
},
setItem() {},
},
K;
try {
(K = localStorage), (M = K);
} catch {
(K = G), (M = G);
}
var S = {
getItem: (t) => M.getItem(t),
setItem: (t, e) => M.setItem(t, e),
disableWritingLocalStorage() {
M = G;
},
disable() {
localStorage.clear(), (M = G);
},
enable() {
M = K;
},
};
window.TypeDoc ||= {
disableWritingLocalStorage() {
S.disableWritingLocalStorage();
},
disableLocalStorage: () => {
S.disable();
},
enableLocalStorage: () => {
S.enable();
},
};
window.translations ||= {
copy: "Copy",
copied: "Copied!",
normally_hidden:
"This member is normally hidden due to your filter settings.",
hierarchy_expand: "Expand",
hierarchy_collapse: "Collapse",
search_index_not_available: "The search index is not available",
search_no_results_found_for_0: "No results found for {0}",
folder: "Folder",
kind_1: "Project",
kind_2: "Module",
kind_4: "Namespace",
kind_8: "Enumeration",
kind_16: "Enumeration Member",
kind_32: "Variable",
kind_64: "Function",
kind_128: "Class",
kind_256: "Interface",
kind_512: "Constructor",
kind_1024: "Property",
kind_2048: "Method",
kind_4096: "Call Signature",
kind_8192: "Index Signature",
kind_16384: "Constructor Signature",
kind_32768: "Parameter",
kind_65536: "Type Literal",
kind_131072: "Type Parameter",
kind_262144: "Accessor",
kind_524288: "Get Signature",
kind_1048576: "Set Signature",
kind_2097152: "Type Alias",
kind_4194304: "Reference",
kind_8388608: "Document",
};
var pe = [];
function X(t, e) {
pe.push({ selector: e, constructor: t });
}
var Z = class {
alwaysVisibleMember = null;
constructor() {
this.createComponents(document.body),
this.ensureFocusedElementVisible(),
this.listenForCodeCopies(),
window.addEventListener("hashchange", () =>
this.ensureFocusedElementVisible(),
),
document.body.style.display ||
(this.ensureFocusedElementVisible(),
this.updateIndexVisibility(),
this.scrollToHash());
}
createComponents(e) {
pe.forEach((n) => {
e.querySelectorAll(n.selector).forEach((r) => {
r.dataset.hasInstance ||
(new n.constructor({ el: r, app: this }),
(r.dataset.hasInstance = String(!0)));
});
});
}
filterChanged() {
this.ensureFocusedElementVisible();
}
showPage() {
document.body.style.display &&
(document.body.style.removeProperty("display"),
this.ensureFocusedElementVisible(),
this.updateIndexVisibility(),
this.scrollToHash());
}
scrollToHash() {
if (location.hash) {
let e = document.getElementById(location.hash.substring(1));
if (!e) return;
e.scrollIntoView({ behavior: "instant", block: "start" });
}
}
ensureActivePageVisible() {
let e = document.querySelector(".tsd-navigation .current"),
n = e?.parentElement;
for (; n && !n.classList.contains(".tsd-navigation"); )
n instanceof HTMLDetailsElement && (n.open = !0), (n = n.parentElement);
if (e && !rt(e)) {
let r =
e.getBoundingClientRect().top -
document.documentElement.clientHeight / 4;
(document.querySelector(".site-menu").scrollTop = r),
(document.querySelector(".col-sidebar").scrollTop = r);
}
}
updateIndexVisibility() {
let e = document.querySelector(".tsd-index-content"),
n = e?.open;
e && (e.open = !0),
document.querySelectorAll(".tsd-index-section").forEach((r) => {
r.style.display = "block";
let i = Array.from(r.querySelectorAll(".tsd-index-link")).every(
(s) => s.offsetParent == null,
);
r.style.display = i ? "none" : "block";
}),
e && (e.open = n);
}
ensureFocusedElementVisible() {
if (
(this.alwaysVisibleMember &&
(this.alwaysVisibleMember.classList.remove("always-visible"),
this.alwaysVisibleMember.firstElementChild.remove(),
(this.alwaysVisibleMember = null)),
!location.hash)
)
return;
let e = document.getElementById(location.hash.substring(1));
if (!e) return;
let n = e.parentElement;
for (; n && n.tagName !== "SECTION"; ) n = n.parentElement;
if (!n) return;
let r = n.offsetParent == null,
i = n;
for (; i !== document.body; )
i instanceof HTMLDetailsElement && (i.open = !0), (i = i.parentElement);
if (n.offsetParent == null) {
(this.alwaysVisibleMember = n), n.classList.add("always-visible");
let s = document.createElement("p");
s.classList.add("warning"),
(s.textContent = window.translations.normally_hidden),
n.prepend(s);
}
r && e.scrollIntoView();
}
listenForCodeCopies() {
document.querySelectorAll("pre > button").forEach((e) => {
let n;
e.addEventListener("click", () => {
e.previousElementSibling instanceof HTMLElement &&
navigator.clipboard.writeText(
e.previousElementSibling.innerText.trim(),
),
(e.textContent = window.translations.copied),
e.classList.add("visible"),
clearTimeout(n),
(n = setTimeout(() => {
e.classList.remove("visible"),
(n = setTimeout(() => {
e.textContent = window.translations.copy;
}, 100));
}, 1e3));
});
});
}
};
function rt(t) {
let e = t.getBoundingClientRect(),
n = Math.max(document.documentElement.clientHeight, window.innerHeight);
return !(e.bottom < 0 || e.top - n >= 0);
}
var fe = (t, e = 100) => {
let n;
return () => {
clearTimeout(n), (n = setTimeout(() => t(), e));
};
};
var Ie = nt(ye(), 1);
async function R(t) {
let e = Uint8Array.from(atob(t), (s) => s.charCodeAt(0)),
r = new Blob([e])
.stream()
.pipeThrough(new DecompressionStream("deflate")),
i = await new Response(r).text();
return JSON.parse(i);
}
var Y = "closing",
ae = "tsd-overlay";
function it() {
let t = Math.abs(window.innerWidth - document.documentElement.clientWidth);
(document.body.style.overflow = "hidden"),
(document.body.style.paddingRight = `${t}px`);
}
function st() {
document.body.style.removeProperty("overflow"),
document.body.style.removeProperty("padding-right");
}
function xe(t, e) {
t.addEventListener("animationend", () => {
t.classList.contains(Y) &&
(t.classList.remove(Y),
document.getElementById(ae)?.remove(),
t.close(),
st());
}),
t.addEventListener("cancel", (n) => {
n.preventDefault(), ve(t);
}),
e?.closeOnClick &&
document.addEventListener(
"click",
(n) => {
t.open && !t.contains(n.target) && ve(t);
},
!0,
);
}
function Ee(t) {
if (t.open) return;
let e = document.createElement("div");
(e.id = ae), document.body.appendChild(e), t.showModal(), it();
}
function ve(t) {
if (!t.open) return;
document.getElementById(ae)?.classList.add(Y), t.classList.add(Y);
}
var I = class {
el;
app;
constructor(e) {
(this.el = e.el), (this.app = e.app);
}
};
var be = document.head.appendChild(document.createElement("style"));
be.dataset.for = "filters";
var le = {};
function we(t) {
for (let e of t.split(/\s+/)) if (le.hasOwnProperty(e) && !le[e]) return !0;
return !1;
}
var ee = class extends I {
key;
value;
constructor(e) {
super(e),
(this.key = `filter-${this.el.name}`),
(this.value = this.el.checked),
this.el.addEventListener("change", () => {
this.setLocalStorage(this.el.checked);
}),
this.setLocalStorage(this.fromLocalStorage()),
(be.innerHTML += `html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; }
`),
this.app.updateIndexVisibility();
}
fromLocalStorage() {
let e = S.getItem(this.key);
return e ? e === "true" : this.el.checked;
}
setLocalStorage(e) {
S.setItem(this.key, e.toString()),
(this.value = e),
this.handleValueChange();
}
handleValueChange() {
(this.el.checked = this.value),
document.documentElement.classList.toggle(this.key, this.value),
(le[`tsd-is-${this.el.name}`] = this.value),
this.app.filterChanged(),
this.app.updateIndexVisibility();
}
};
var Le = 0;
async function Se(t, e) {
if (!window.searchData) return;
let n = await R(window.searchData);
(t.data = n), (t.index = Ie.Index.load(n.index)), (e.innerHTML = "");
}
function _e() {
let t = document.getElementById("tsd-search-trigger"),
e = document.getElementById("tsd-search"),
n = document.getElementById("tsd-search-input"),
r = document.getElementById("tsd-search-results"),
i = document.getElementById("tsd-search-script"),
s = document.getElementById("tsd-search-status");
if (!(t && e && n && r && i && s))
throw new Error("Search controls missing");
let o = { base: document.documentElement.dataset.base };
o.base.endsWith("/") || (o.base += "/"),
i.addEventListener("error", () => {
let a = window.translations.search_index_not_available;
Pe(s, a);
}),
i.addEventListener("load", () => {
Se(o, s);
}),
Se(o, s),
ot({ trigger: t, searchEl: e, results: r, field: n, status: s }, o);
}
function ot(t, e) {
let { field: n, results: r, searchEl: i, status: s, trigger: o } = t;
xe(i, { closeOnClick: !0 });
function a() {
Ee(i), n.setSelectionRange(0, n.value.length);
}
o.addEventListener("click", a),
n.addEventListener(
"input",
fe(() => {
at(r, n, s, e);
}, 200),
),
n.addEventListener("keydown", (l) => {
if (r.childElementCount === 0 || l.ctrlKey || l.metaKey || l.altKey)
return;
let d = n.getAttribute("aria-activedescendant"),
f = d ? document.getElementById(d) : null;
if (f) {
let p = !1,
v = !1;
switch (l.key) {
case "Home":
case "End":
case "ArrowLeft":
case "ArrowRight":
v = !0;
break;
case "ArrowDown":
case "ArrowUp":
p = l.shiftKey;
break;
}
(p || v) && ke(n);
}
if (!l.shiftKey)
switch (l.key) {
case "Enter":
f?.querySelector("a")?.click();
break;
case "ArrowUp":
Te(r, n, f, -1), l.preventDefault();
break;
case "ArrowDown":
Te(r, n, f, 1), l.preventDefault();
break;
}
});
function c() {
ke(n);
}
n.addEventListener("change", c),
n.addEventListener("blur", c),
n.addEventListener("click", c),
document.body.addEventListener("keydown", (l) => {
if (l.altKey || l.metaKey || l.shiftKey) return;
let d = l.ctrlKey && l.key === "k",
f = !l.ctrlKey && !ut() && l.key === "/";
(d || f) && (l.preventDefault(), a());
});
}
function at(t, e, n, r) {
if (!r.index || !r.data) return;
(t.innerHTML = ""), (n.innerHTML = ""), (Le += 1);
let i = e.value.trim(),
s;
if (i) {
let a = i
.split(" ")
.map((c) => (c.length ? `*${c}*` : ""))
.join(" ");
s = r.index.search(a).filter(({ ref: c }) => {
let l = r.data.rows[Number(c)].classes;
return !l || !we(l);
});
} else s = [];
if (s.length === 0 && i) {
let a = window.translations.search_no_results_found_for_0.replace(
"{0}",
` "<strong>${te(i)}</strong>" `,
);
Pe(n, a);
return;
}
for (let a = 0; a < s.length; a++) {
let c = s[a],
l = r.data.rows[Number(c.ref)],
d = 1;
l.name.toLowerCase().startsWith(i.toLowerCase()) &&
(d *= 10 / (1 + Math.abs(l.name.length - i.length))),
(c.score *= d);
}
s.sort((a, c) => c.score - a.score);
let o = Math.min(10, s.length);
for (let a = 0; a < o; a++) {
let c = r.data.rows[Number(s[a].ref)],
d = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" class="tsd-kind-icon" aria-label="${window.translations[
`kind_${c.kind}`
].replaceAll('"', """)}"><use href="#icon-${
c.icon || c.kind
}"></use></svg>`,
f = Ce(c.name, i);
globalThis.DEBUG_SEARCH_WEIGHTS &&
(f += ` (score: ${s[a].score.toFixed(2)})`),
c.parent &&
(f = `<span class="parent">
${Ce(c.parent, i)}.</span>${f}`);
let p = document.createElement("li");
(p.id = `tsd-search:${Le}-${a}`),
(p.role = "option"),
(p.ariaSelected = "false"),
(p.classList.value = c.classes ?? "");
let v = document.createElement("a");
(v.tabIndex = -1),
(v.href = r.base + c.url),
(v.innerHTML = d + `<span class="text">${f}</span>`),
p.append(v),
t.appendChild(p);
}
}
function Te(t, e, n, r) {
let i;
if (
(r === 1
? (i = n?.nextElementSibling || t.firstElementChild)
: (i = n?.previousElementSibling || t.lastElementChild),
i !== n)
) {
if (!i || i.role !== "option") {
console.error("Option missing");
return;
}
(i.ariaSelected = "true"),
i.scrollIntoView({ behavior: "smooth", block: "nearest" }),
e.setAttribute("aria-activedescendant", i.id),
n?.setAttribute("aria-selected", "false");
}
}
function ke(t) {
let e = t.getAttribute("aria-activedescendant");
(e ? document.getElementById(e) : null)?.setAttribute(
"aria-selected",
"false",
),
t.setAttribute("aria-activedescendant", "");
}
function Ce(t, e) {
if (e === "") return t;
let n = t.toLocaleLowerCase(),
r = e.toLocaleLowerCase(),
i = [],
s = 0,
o = n.indexOf(r);
for (; o != -1; )
i.push(
te(t.substring(s, o)),
`<mark>${te(t.substring(o, o + r.length))}</mark>`,
),
(s = o + r.length),
(o = n.indexOf(r, s));
return i.push(te(t.substring(s))), i.join("");
}
var lt = {
"&": "&",
"<": "<",
">": ">",
"'": "'",
'"': """,
};
function te(t) {
return t.replace(/[&<>"'"]/g, (e) => lt[e]);
}
function Pe(t, e) {
t.innerHTML = e ? `<div>${e}</div>` : "";
}
var ct = [
"button",
"checkbox",
"file",
"hidden",
"image",
"radio",
"range",
"reset",
"submit",
];
function ut() {
let t = document.activeElement;
return t
? t.isContentEditable ||
t.tagName === "TEXTAREA" ||
t.tagName === "SEARCH"
? !0
: t.tagName === "INPUT" && !ct.includes(t.type)
: !1;
}
var D = "mousedown",
Me = "mousemove",
$ = "mouseup",
ne = { x: 0, y: 0 },
Qe = !1,
ce = !1,
dt = !1,
F = !1,
Oe = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
navigator.userAgent,
);
document.documentElement.classList.add(Oe ? "is-mobile" : "not-mobile");
Oe &&
"ontouchstart" in document.documentElement &&
((dt = !0), (D = "touchstart"), (Me = "touchmove"), ($ = "touchend"));
document.addEventListener(D, (t) => {
(ce = !0), (F = !1);
let e = D == "touchstart" ? t.targetTouches[0] : t;
(ne.y = e.pageY || 0), (ne.x = e.pageX || 0);
});
document.addEventListener(Me, (t) => {
if (ce && !F) {
let e = D == "touchstart" ? t.targetTouches[0] : t,
n = ne.x - (e.pageX || 0),
r = ne.y - (e.pageY || 0);
F = Math.sqrt(n * n + r * r) > 10;
}
});
document.addEventListener($, () => {
ce = !1;
});
document.addEventListener("click", (t) => {
Qe && (t.preventDefault(), t.stopImmediatePropagation(), (Qe = !1));
});
var re = class extends I {
active;
className;
constructor(e) {
super(e),
(this.className = this.el.dataset.toggle || ""),
this.el.addEventListener($, (n) => this.onPointerUp(n)),
this.el.addEventListener("click", (n) => n.preventDefault()),
document.addEventListener(D, (n) => this.onDocumentPointerDown(n)),
document.addEventListener($, (n) => this.onDocumentPointerUp(n));
}
setActive(e) {
if (this.active == e) return;
(this.active = e),
document.documentElement.classList.toggle("has-" + this.className, e),
this.el.classList.toggle("active", e);
let n = (this.active ? "to-has-" : "from-has-") + this.className;
document.documentElement.classList.add(n),
setTimeout(() => document.documentElement.classList.remove(n), 500);
}
onPointerUp(e) {
F || (this.setActive(!0), e.preventDefault());
}
onDocumentPointerDown(e) {
if (this.active) {
if (e.target.closest(".col-sidebar, .tsd-filter-group")) return;
this.setActive(!1);
}
}
onDocumentPointerUp(e) {
if (!F && this.active && e.target.closest(".col-sidebar")) {
let n = e.target.closest("a");
if (n) {
let r = window.location.href;
r.indexOf("#") != -1 && (r = r.substring(0, r.indexOf("#"))),
n.href.substring(0, r.length) == r &&
setTimeout(() => this.setActive(!1), 250);
}
}
}
};
var ue = new Map(),
de = class {
open;
accordions = [];
key;
constructor(e, n) {
(this.key = e), (this.open = n);
}
add(e) {
this.accordions.push(e),
(e.open = this.open),
e.addEventListener("toggle", () => {
this.toggle(e.open);
});
}
toggle(e) {
for (let n of this.accordions) n.open = e;
S.setItem(this.key, e.toString());
}
},
ie = class extends I {
constructor(e) {
super(e);
let n = this.el.querySelector("summary"),
r = n.querySelector("a");
r &&
r.addEventListener("click", () => {
location.assign(r.href);
});
let i = `tsd-accordion-${
n.dataset.key ??
n.textContent.trim().replace(/\s+/g, "-").toLowerCase()
}`,
s;
if (ue.has(i)) s = ue.get(i);
else {
let o = S.getItem(i),
a = o ? o === "true" : this.el.open;
(s = new de(i, a)), ue.set(i, s);
}
s.add(this.el);
}
};
function He(t) {
let e = S.getItem("tsd-theme") || "os";
(t.value = e),
Ae(e),
t.addEventListener("change", () => {
S.setItem("tsd-theme", t.value), Ae(t.value);
});
}
function Ae(t) {
document.documentElement.dataset.theme = t;
}
var se;
function Ne() {
let t = document.getElementById("tsd-nav-script");
t && (t.addEventListener("load", Re), Re());
}
async function Re() {
let t = document.getElementById("tsd-nav-container");
if (!t || !window.navigationData) return;
let e = await R(window.navigationData);
(se = document.documentElement.dataset.base),
se.endsWith("/") || (se += "/"),
(t.innerHTML = "");
for (let n of e) Be(n, t, []);
window.app.createComponents(t),
window.app.showPage(),
window.app.ensureActivePageVisible();
}
function Be(t, e, n) {
let r = e.appendChild(document.createElement("li"));
if (t.children) {
let i = [...n, t.text],
s = r.appendChild(document.createElement("details"));
s.className = t.class ? `${t.class} tsd-accordion` : "tsd-accordion";
let o = s.appendChild(document.createElement("summary"));
(o.className = "tsd-accordion-summary"),
(o.dataset.key = i.join("$")),
(o.innerHTML =
'<svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="#icon-chevronDown"></use></svg>'),
De(t, o);
let a = s.appendChild(document.createElement("div"));
a.className = "tsd-accordion-details";
let c = a.appendChild(document.createElement("ul"));
c.className = "tsd-nested-navigation";
for (let l of t.children) Be(l, c, i);
} else De(t, r, t.class);
}
function De(t, e, n) {
if (t.path) {
let r = e.appendChild(document.createElement("a"));
if (
((r.href = se + t.path),
n && (r.className = n),
location.pathname === r.pathname &&
!r.href.includes("#") &&
(r.classList.add("current"), (r.ariaCurrent = "page")),
t.kind)
) {
let i = window.translations[`kind_${t.kind}`].replaceAll('"', """);
r.innerHTML = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" class="tsd-kind-icon" aria-label="${i}"><use href="#icon-${
t.icon || t.kind
}"></use></svg>`;
}
r.appendChild(Fe(t.text, document.createElement("span")));
} else {
let r = e.appendChild(document.createElement("span")),
i = window.translations.folder.replaceAll('"', """);
(r.innerHTML = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" class="tsd-kind-icon" aria-label="${i}"><use href="#icon-folder"></use></svg>`),
r.appendChild(Fe(t.text, document.createElement("span")));
}
}
function Fe(t, e) {
let n = t.split(
/(?<=[^A-Z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[_-])(?=[^_-])/,
);
for (let r = 0; r < n.length; ++r)
r !== 0 && e.appendChild(document.createElement("wbr")),
e.appendChild(document.createTextNode(n[r]));
return e;
}
var oe = document.documentElement.dataset.base;
oe.endsWith("/") || (oe += "/");
function $e() {
document.querySelector(".tsd-full-hierarchy")
? ht()
: document.querySelector(".tsd-hierarchy") && pt();
}
function ht() {
document.addEventListener("click", (r) => {
let i = r.target;
for (; i.parentElement && i.parentElement.tagName != "LI"; )
i = i.parentElement;
i.dataset.dropdown &&
(i.dataset.dropdown = String(i.dataset.dropdown !== "true"));
});
let t = new Map(),
e = new Set();
for (let r of document.querySelectorAll(
".tsd-full-hierarchy [data-refl]",
)) {
let i = r.querySelector("ul");
t.has(r.dataset.refl)
? e.add(r.dataset.refl)
: i && t.set(r.dataset.refl, i);
}
for (let r of e) n(r);
function n(r) {
let i = t.get(r).cloneNode(!0);
i.querySelectorAll("[id]").forEach((s) => {
s.removeAttribute("id");
}),
i.querySelectorAll("[data-dropdown]").forEach((s) => {
s.dataset.dropdown = "false";
});
for (let s of document.querySelectorAll(`[data-refl="${r}"]`)) {
let o = gt(),
a = s.querySelector("ul");
s.insertBefore(o, a),
(o.dataset.dropdown = String(!!a)),
a || s.appendChild(i.cloneNode(!0));
}
}
}
function pt() {
let t = document.getElementById("tsd-hierarchy-script");
t && (t.addEventListener("load", Ve), Ve());
}
async function Ve() {
let t = document.querySelector(".tsd-panel.tsd-hierarchy:has(h4 a)");
if (!t || !window.hierarchyData) return;
let e = +t.dataset.refl,
n = await R(window.hierarchyData),
r = t.querySelector("ul"),
i = document.createElement("ul");
if (
(i.classList.add("tsd-hierarchy"),
ft(i, n, e),
r.querySelectorAll("li").length == i.querySelectorAll("li").length)
)
return;
let s = document.createElement("span");
s.classList.add("tsd-hierarchy-toggle"),
(s.textContent = window.translations.hierarchy_expand),
t.querySelector("h4 a")?.insertAdjacentElement("afterend", s),
s.insertAdjacentText("beforebegin", ", "),
s.addEventListener("click", () => {
s.textContent === window.translations.hierarchy_expand
? (r.insertAdjacentElement("afterend", i),
r.remove(),
(s.textContent = window.translations.hierarchy_collapse))
: (i.insertAdjacentElement("afterend", r),
i.remove(),
(s.textContent = window.translations.hierarchy_expand));
});
}
function ft(t, e, n) {
let r = e.roots.filter((i) => mt(e, i, n));
for (let i of r) t.appendChild(je(e, i, n));
}
function je(t, e, n, r = new Set()) {
if (r.has(e)) return;
r.add(e);
let i = t.reflections[e],
s = document.createElement("li");
if ((s.classList.add("tsd-hierarchy-item"), e === n)) {
let o = s.appendChild(document.createElement("span"));
(o.textContent = i.name), o.classList.add("tsd-hierarchy-target");
} else {
for (let a of i.uniqueNameParents || []) {
let c = t.reflections[a],
l = s.appendChild(document.createElement("a"));
(l.textContent = c.name),
(l.href = oe + c.url),
(l.className = c.class + " tsd-signature-type"),
s.append(document.createTextNode("."));
}
let o = s.appendChild(document.createElement("a"));
(o.textContent = t.reflections[e].name),
(o.href = oe + i.url),
(o.className = i.class + " tsd-signature-type");
}
if (i.children) {
let o = s.appendChild(document.createElement("ul"));
o.classList.add("tsd-hierarchy");
for (let a of i.children) {
let c = je(t, a, n, r);
c && o.appendChild(c);
}
}
return r.delete(e), s;
}
function mt(t, e, n) {
if (e === n) return !0;
let r = new Set(),
i = [t.reflections[e]];
for (; i.length; ) {
let s = i.pop();
if (!r.has(s)) {
r.add(s);
for (let o of s.children || []) {
if (o === n) return !0;
i.push(t.reflections[o]);
}
}
}
return !1;
}
function gt() {
let t = document.createElementNS("http://www.w3.org/2000/svg", "svg");
return (
t.setAttribute("width", "20"),
t.setAttribute("height", "20"),
t.setAttribute("viewBox", "0 0 24 24"),
t.setAttribute("fill", "none"),
(t.innerHTML = '<use href="#icon-chevronDown"></use>'),
t
);
}
X(re, "a[data-toggle]");
X(ie, ".tsd-accordion");
X(ee, ".tsd-filter-item input[type=checkbox]");
var qe = document.getElementById("tsd-theme");
qe && He(qe);
var yt = new Z();
Object.defineProperty(window, "app", { value: yt });
_e();
Ne();
$e();
"virtualKeyboard" in navigator &&
(navigator.virtualKeyboard.overlaysContent = !0);
})();
/*! Bundled license information:
lunr/lunr.js:
(**
* lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9
* Copyright (C) 2020 Oliver Nightingale
* @license MIT
*)
(*!
* lunr.utils
* Copyright (C) 2020 Oliver Nightingale
*)
(*!
* lunr.Set
* Copyright (C) 2020 Oliver Nightingale
*)
(*!
* lunr.tokenizer
* Copyright (C) 2020 Oliver Nightingale
*)
(*!
* lunr.Pipeline
* Copyright (C) 2020 Oliver Nightingale
*)
(*!
* lunr.Vector
* Copyright (C) 2020 Oliver Nightingale
*)
(*!
* lunr.stemmer
* Copyright (C) 2020 Oliver Nightingale
* Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt
*)
(*!
* lunr.stopWordFilter
* Copyright (C) 2020 Oliver Nightingale
*)
(*!
* lunr.trimmer
* Copyright (C) 2020 Oliver Nightingale
*)
(*!
* lunr.TokenSet
* Copyright (C) 2020 Oliver Nightingale
*)
(*!
* lunr.Index
* Copyright (C) 2020 Oliver Nightingale
*)
(*!
* lunr.Builder
* Copyright (C) 2020 Oliver Nightingale
*)
*/
```
--------------------------------------------------------------------------------
/src/tools/populate-content.ts:
--------------------------------------------------------------------------------
```typescript
import { Tool } from "@modelcontextprotocol/sdk/types.js";
import * as fs from "fs/promises";
import * as path from "path";
import {
handleMemoryRecall,
handleMemoryEnhancedRecommendation,
handleMemoryIntelligentAnalysis,
} from "../memory/index.js";
interface PopulationOptions {
analysisId: string;
docsPath: string;
populationLevel: "basic" | "comprehensive" | "intelligent";
includeProjectSpecific: boolean;
preserveExisting: boolean;
technologyFocus?: string[];
}
interface TutorialContent {
title: string;
description: string;
content: string;
codeExamples?: string[];
}
interface ContentPlan {
tutorials: TutorialContent[];
howToGuides: any[];
reference: any[];
explanation: any[];
}
// ProjectContext interface - currently unused but kept for future enhancements
// interface ProjectContext {
// primaryLanguage: string;
// frameworks: any[];
// testingFrameworks: any[];
// dependencies: any;
// devopsTools?: DevOpsToolProfile;
// }
interface DevOpsToolProfile {
containerization: ContainerTechnology[];
orchestration: OrchestrationTechnology[];
cicd: CICDTechnology[];
configuration: ConfigManagementTechnology[];
monitoring: MonitoringTechnology[];
security: SecurityTechnology[];
}
interface ContainerTechnology {
name: string;
version?: string;
configFiles: string[];
usage: string;
}
interface OrchestrationTechnology {
name: string;
manifests?: string[];
resources?: string[];
namespaces?: string[];
}
interface CICDTechnology {
name: string;
pipelines?: string[];
tasks?: string[];
triggers?: string[];
}
interface ConfigManagementTechnology {
name: string;
playbooks?: string[];
roles?: string[];
inventory?: string[];
vaultFiles?: string[];
}
interface MonitoringTechnology {
name: string;
}
interface SecurityTechnology {
name: string;
}
// Interfaces for future extensibility
// interface LanguageContentGenerator {
// detectFrameworks(analysis: any): any[];
// generateContent(frameworks: any[], context: ProjectContext): any;
// }
// interface DevOpsContentGenerator {
// detectDevOpsTools(analysis: any): DevOpsToolProfile;
// generateDevOpsContent(tools: DevOpsToolProfile, context: ProjectContext): any;
// }
interface PopulationResult {
success: boolean;
filesCreated: number;
contentPlan: ContentPlan;
populationMetrics: {
coverage: number;
completeness: number;
projectSpecificity: number;
};
nextSteps: string[];
}
class ContentPopulationEngine {
private analysisCache: Map<string, any> = new Map();
private memoryInsights: any = null;
private similarProjects: any[] = [];
async populateContent(
options: PopulationOptions,
context?: any,
): Promise<PopulationResult> {
// Report initial progress
if (context?.meta?.progressToken) {
await context.meta.reportProgress?.({ progress: 0, total: 100 });
}
await context?.info?.("📝 Starting Diataxis content population...");
// 1. Retrieve and validate repository analysis
await context?.info?.("📊 Retrieving repository analysis...");
const analysis = await this.getRepositoryAnalysis(options.analysisId);
if (context?.meta?.progressToken) {
await context.meta.reportProgress?.({ progress: 20, total: 100 });
}
// 2. Get memory-enhanced insights for intelligent content generation
await context?.info?.(
"🧠 Loading memory insights for intelligent generation...",
);
await this.loadMemoryInsights(analysis, options);
if (context?.meta?.progressToken) {
await context.meta.reportProgress?.({ progress: 40, total: 100 });
}
// 3. Generate content plan based on project characteristics AND memory insights
await context?.info?.("🗺️ Generating intelligent content plan...");
const contentPlan = await this.generateIntelligentContentPlan(
analysis,
options.populationLevel,
this.memoryInsights,
);
// 4. Generate memory-informed content for each Diataxis category
const tutorials = await this.generateMemoryInformedTutorialContent(
contentPlan.tutorials,
analysis,
this.memoryInsights,
);
const howTos = await this.generateMemoryInformedHowToContent(
contentPlan.howToGuides,
analysis,
this.memoryInsights,
);
const reference = await this.generateMemoryInformedReferenceContent(
contentPlan.reference,
analysis,
this.memoryInsights,
);
const explanation = await this.generateMemoryInformedExplanationContent(
contentPlan.explanation,
analysis,
this.memoryInsights,
);
// 5. Write content to documentation structure
const filesCreated = await this.writeContentToStructure(
options.docsPath,
{ tutorials, howTos, reference, explanation },
options.preserveExisting,
);
// 6. Generate cross-references and navigation updates
await context?.info?.("🔗 Generating cross-references and navigation...");
await this.updateNavigationAndCrossReferences(
options.docsPath,
contentPlan,
);
if (context?.meta?.progressToken) {
await context.meta.reportProgress?.({ progress: 100, total: 100 });
}
await context?.info?.(
`✅ Content population complete! Generated ${filesCreated} file(s)`,
);
return {
success: true,
filesCreated,
contentPlan,
populationMetrics: this.calculatePopulationMetrics(
filesCreated,
contentPlan,
),
nextSteps: this.generateMemoryInformedNextSteps(
analysis,
contentPlan,
this.memoryInsights,
),
};
}
private async getRepositoryAnalysis(analysisId: string): Promise<any> {
// First try to get analysis from memory system
try {
const memoryRecall = await this.getFromMemorySystem(analysisId);
if (memoryRecall) {
return memoryRecall;
}
} catch (error) {
console.warn("Failed to retrieve from memory system:", error);
}
// Fallback to reading from cached analysis file
const analysisPath = path.join(
".documcp",
"analyses",
`${analysisId}.json`,
);
try {
const content = await fs.readFile(analysisPath, "utf-8");
return JSON.parse(content);
} catch {
throw new Error(
`Repository analysis with ID '${analysisId}' not found. Please run analyze_repository first.`,
);
}
}
private async getFromMemorySystem(analysisId: string): Promise<any> {
try {
const result = await handleMemoryRecall({
query: analysisId,
type: "analysis",
limit: 1,
});
// Handle the memory recall result structure
if (result && result.memories && result.memories.length > 0) {
const memory = result.memories[0];
// Handle wrapped content structure
if (
memory.data &&
memory.data.content &&
Array.isArray(memory.data.content)
) {
// Extract the JSON from the first text content
const firstContent = memory.data.content[0];
if (
firstContent &&
firstContent.type === "text" &&
firstContent.text
) {
try {
return JSON.parse(firstContent.text);
} catch (parseError) {
console.warn(
"Failed to parse analysis content from memory:",
parseError,
);
return memory.data;
}
}
}
// Try direct content access (legacy format)
if (memory.content) {
return memory.content;
}
// Try data field
if (memory.data) {
return memory.data;
}
}
return null;
} catch (error) {
console.warn("Memory system recall failed:", error);
return null;
}
}
private async loadMemoryInsights(
analysis: any,
options: PopulationOptions,
): Promise<void> {
try {
// Get similar projects from memory system
const similarProjectsQuery = `${
analysis.metadata?.primaryLanguage || ""
} ${analysis.metadata?.ecosystem || ""} documentation`;
const similarProjects = await handleMemoryRecall({
query: similarProjectsQuery,
type: "recommendation",
limit: 5,
});
// Get memory-enhanced analysis
const enhancedAnalysis = await handleMemoryIntelligentAnalysis({
projectPath: analysis.projectPath || "",
baseAnalysis: analysis,
});
// Get memory-enhanced recommendations for content strategy
const enhancedRecommendations = await handleMemoryEnhancedRecommendation({
projectPath: analysis.projectPath || "",
baseRecommendation: {
contentStrategy: "diataxis",
populationLevel: options.populationLevel,
},
projectFeatures: {
ecosystem: analysis.metadata?.ecosystem || "unknown",
primaryLanguage: analysis.metadata?.primaryLanguage || "unknown",
complexity: analysis.complexity || "medium",
hasTests: analysis.structure?.hasTests || false,
hasCI: analysis.structure?.hasCI || false,
},
});
this.memoryInsights = {
similarProjects: similarProjects.memories || [],
enhancedAnalysis: enhancedAnalysis,
enhancedRecommendations: enhancedRecommendations,
patterns: this.extractPatternsFromSimilarProjects(
similarProjects.memories || [],
),
};
this.similarProjects = similarProjects.memories || [];
} catch (error) {
console.warn("Failed to load memory insights:", error);
// Fallback to minimal insights
this.memoryInsights = {
similarProjects: [],
enhancedAnalysis: null,
enhancedRecommendations: null,
patterns: {},
};
}
}
private extractPatternsFromSimilarProjects(projects: any[]): any {
const patterns = {
commonFrameworks: {} as Record<string, number>,
successfulSSGs: {} as Record<string, number>,
documentationStructures: {} as Record<string, number>,
deploymentStrategies: {} as Record<string, number>,
};
projects.forEach((project) => {
const content = project.content || {};
// Extract framework patterns
if (content.frameworks) {
content.frameworks.forEach((framework: string) => {
patterns.commonFrameworks[framework] =
(patterns.commonFrameworks[framework] || 0) + 1;
});
}
// Extract SSG success patterns
if (content.recommendedSSG) {
patterns.successfulSSGs[content.recommendedSSG] =
(patterns.successfulSSGs[content.recommendedSSG] || 0) + 1;
}
// Extract documentation structure patterns
if (content.documentationApproach) {
patterns.documentationStructures[content.documentationApproach] =
(patterns.documentationStructures[content.documentationApproach] ||
0) + 1;
}
// Extract deployment patterns
if (content.deploymentStrategy) {
patterns.deploymentStrategies[content.deploymentStrategy] =
(patterns.deploymentStrategies[content.deploymentStrategy] || 0) + 1;
}
});
return patterns;
}
private async generateIntelligentContentPlan(
analysis: any,
level: string,
_memoryInsights: any,
): Promise<ContentPlan> {
const plan: ContentPlan = {
tutorials: [],
howToGuides: [],
reference: [],
explanation: [],
};
// Generate tutorials based on project type AND memory patterns
plan.tutorials = this.generateMemoryInformedTutorialPlan(
analysis,
level,
_memoryInsights,
);
// Generate how-to guides for common tasks (enhanced with successful patterns)
plan.howToGuides = this.generateMemoryInformedHowToPlan(
analysis,
level,
_memoryInsights,
);
// Generate reference documentation (based on similar project structures)
plan.reference = this.generateMemoryInformedReferencePlan(
analysis,
level,
_memoryInsights,
);
// Generate explanation content (leveraging successful explanation patterns)
plan.explanation = this.generateMemoryInformedExplanationPlan(
analysis,
level,
_memoryInsights,
);
return plan;
}
private generateMemoryInformedTutorialPlan(
analysis: any,
_level: string,
_memoryInsights: any,
): TutorialContent[] {
const tutorials: TutorialContent[] = [];
const similarProjects = _memoryInsights?.similarProjects || [];
tutorials.push({
title: `Getting Started with ${
analysis.metadata?.projectName || "the Project"
}`,
description: this.generateMemoryInformedDescription(
analysis,
similarProjects,
"getting-started",
),
content: this.generateMemoryInformedGettingStartedContent(
analysis,
_memoryInsights,
),
codeExamples: this.generateMemoryInformedGettingStartedExamples(
analysis,
_memoryInsights,
),
});
// Add technology-specific tutorials based on what worked for similar projects
const ecosystem =
analysis.metadata?.ecosystem || analysis.technologies?.runtime;
if (
ecosystem === "Node.js" ||
ecosystem === "javascript" ||
ecosystem === "typescript"
) {
const nodeSuccessPatterns =
this.extractNodeSuccessPatterns(similarProjects);
tutorials.push({
title: this.generateMemoryInformedTutorialTitle(
"environment-setup",
nodeSuccessPatterns,
analysis,
),
description:
"Configure your development environment based on proven successful patterns",
content: this.generateMemoryInformedNodeSetupContent(
analysis,
nodeSuccessPatterns,
),
codeExamples: this.generateMemoryInformedNodeSetupExamples(
analysis,
nodeSuccessPatterns,
),
});
}
// Add testing tutorial if tests detected
if (analysis.structure.hasTests) {
tutorials.push({
title: "Writing and Running Tests",
description: "Learn how to test your code effectively",
content: this.generateTestingTutorialContent(analysis),
codeExamples: this.generateTestingExamples(analysis),
});
}
// Add DevOps tutorials based on detected tools
const devopsTools = this.detectDevOpsTools(analysis);
if (devopsTools.containerization.length > 0) {
const containerTech = devopsTools.containerization[0];
tutorials.push({
title: `Containerizing ${analysis.metadata.projectName} with ${containerTech.name}`,
description: `Learn how to containerize your application using ${containerTech.name}`,
content: this.generateContainerTutorialContent(analysis, containerTech),
codeExamples: this.generateContainerExamples(analysis, containerTech),
});
}
if (devopsTools.orchestration.length > 0) {
const orchestrationTech = devopsTools.orchestration[0];
tutorials.push({
title: `Deploying to ${orchestrationTech.name}`,
description: `Deploy your application to ${orchestrationTech.name}`,
content: this.generateOrchestrationTutorialContent(
analysis,
orchestrationTech,
),
codeExamples: this.generateOrchestrationExamples(
analysis,
orchestrationTech,
),
});
}
// Python-specific tutorials
if (analysis.metadata.primaryLanguage === "Python") {
tutorials.push({
title: "Python Virtual Environment Setup",
description: "Set up isolated Python development environment",
content: this.generatePythonEnvironmentContent(analysis),
codeExamples: this.generatePythonEnvironmentExamples(),
});
// Python framework-specific tutorials
const pythonFrameworks = this.detectPythonFrameworks(analysis);
pythonFrameworks.forEach((framework) => {
tutorials.push({
title: `Building Applications with ${framework.name}`,
description: `Complete guide to ${framework.name} development`,
content: this.generatePythonFrameworkTutorialContent(
analysis,
framework,
),
codeExamples: this.generatePythonFrameworkExamples(framework),
});
});
}
return tutorials;
}
private generateHowToPlan(analysis: any, _level: string): any[] {
const howTos: any[] = [];
// Common development tasks
howTos.push({
title: "How to Add a New Feature",
content: this.generateFeatureGuideContent(analysis),
});
howTos.push({
title: "How to Debug Common Issues",
content: this.generateDebuggingGuideContent(analysis),
});
// Deployment guides if CI detected
if (analysis.structure.hasCI) {
howTos.push({
title: "How to Deploy Your Application",
content: this.generateDeploymentGuideContent(analysis),
});
}
return howTos;
}
private generateReferencePlan(analysis: any, _level: string): any[] {
const reference: any[] = [];
// API reference
reference.push({
title: "API Reference",
content: this.generateAPIReference(analysis),
});
// Configuration reference
reference.push({
title: "Configuration Options",
content: this.generateConfigReference(analysis),
});
// CLI reference if applicable
reference.push({
title: "Command Line Interface",
content: this.generateCLIReference(analysis),
});
return reference;
}
private generateExplanationPlan(analysis: any, _level: string): any[] {
const explanations: any[] = [];
// Architecture overview
explanations.push({
title: "Architecture Overview",
content: this.generateArchitectureContent(analysis),
});
// Design decisions
explanations.push({
title: "Design Decisions",
content: this.generateDesignDecisionsContent(analysis),
});
// Technology choices
explanations.push({
title: "Technology Stack",
content: this.generateTechnologyStackContent(analysis),
});
return explanations;
}
// Memory-informed helper methods
private getSuccessfulGettingStartedApproach(
similarProjects: any[],
analysis: any,
): any {
// Analyze successful getting-started approaches from similar projects
const approaches = similarProjects
.filter((p) => p.content?.gettingStartedApproach)
.map((p) => p.content.gettingStartedApproach);
// Return most common successful approach, or default based on project type
return approaches.length > 0
? approaches[0]
: this.getDefaultApproachForProjectType(analysis);
}
private generateMemoryInformedDescription(
analysis: any,
similarProjects: any[],
tutorialType: string,
): string {
const successfulDescriptions = similarProjects
.filter((p) => p.content?.tutorials?.[tutorialType])
.map((p) => p.content.tutorials[tutorialType].description);
if (successfulDescriptions.length > 0) {
// Adapt successful pattern for this project
return `Learn ${
analysis.metadata?.primaryLanguage || "development"
} with ${
analysis.metadata?.projectName || "this project"
} using proven patterns from ${
successfulDescriptions.length
} similar successful projects`;
}
return `Learn ${
analysis.metadata?.primaryLanguage || "development"
} development with ${analysis.metadata?.projectName || "this project"}`;
}
private extractNodeSuccessPatterns(similarProjects: any[]): any {
const nodeProjects = similarProjects.filter(
(p) =>
p.content?.ecosystem === "Node.js" ||
p.content?.primaryLanguage === "TypeScript" ||
p.content?.primaryLanguage === "JavaScript",
);
return {
commonTools: this.extractCommonTools(nodeProjects),
successfulCommands: this.extractSuccessfulCommands(nodeProjects),
recommendedVersions: this.extractRecommendedVersions(nodeProjects),
bestPractices: this.extractBestPractices(nodeProjects),
};
}
private extractCommonTools(projects: any[]): string[] {
const toolCounts: Record<string, number> = {};
projects.forEach((p) => {
(p.content?.tools || []).forEach((tool: string) => {
toolCounts[tool] = (toolCounts[tool] || 0) + 1;
});
});
// Return tools used by >50% of similar projects
const threshold = Math.ceil(projects.length * 0.5);
return Object.entries(toolCounts)
.filter(([_, count]) => count >= threshold)
.map(([tool, _]) => tool);
}
private extractSuccessfulCommands(projects: any[]): Record<string, string[]> {
const commands: Record<string, string[]> = {};
projects.forEach((p) => {
if (p.content?.commands) {
Object.entries(p.content.commands).forEach(([key, cmds]) => {
if (!commands[key]) commands[key] = [];
commands[key].push(...(cmds as string[]));
});
}
});
// Deduplicate and return most common commands
Object.keys(commands).forEach((key) => {
commands[key] = [...new Set(commands[key])];
});
return commands;
}
private extractRecommendedVersions(projects: any[]): Record<string, string> {
const versions: Record<string, Record<string, number>> = {};
projects.forEach((p) => {
if (p.content?.versions) {
Object.entries(p.content.versions).forEach(([tool, version]) => {
if (!versions[tool]) versions[tool] = {};
versions[tool][version as string] =
(versions[tool][version as string] || 0) + 1;
});
}
});
// Return most commonly used versions
const recommendedVersions: Record<string, string> = {};
Object.entries(versions).forEach(([tool, versionCounts]) => {
const mostCommon = Object.entries(versionCounts).sort(
([, a], [, b]) => (b as number) - (a as number),
)[0];
if (mostCommon) {
recommendedVersions[tool] = mostCommon[0];
}
});
return recommendedVersions;
}
private extractBestPractices(projects: any[]): string[] {
const practices: Record<string, number> = {};
projects.forEach((p) => {
(p.content?.bestPractices || []).forEach((practice: string) => {
practices[practice] = (practices[practice] || 0) + 1;
});
});
// Return practices mentioned by >30% of projects
const threshold = Math.ceil(projects.length * 0.3);
return Object.entries(practices)
.filter(([_, count]) => count >= threshold)
.map(([practice, _]) => practice);
}
private getDefaultApproachForProjectType(analysis: any): any {
const projectType = analysis.metadata?.projectType || "library";
const primaryLanguage = analysis.metadata?.primaryLanguage || "JavaScript";
return {
type: projectType,
language: primaryLanguage,
approach: "hands-on",
complexity: "progressive",
};
}
private generateMemoryInformedTutorialTitle(
tutorialType: string,
patterns: any,
analysis: any,
): string {
const projectName = analysis.metadata?.projectName || "Project";
const language = analysis.metadata?.primaryLanguage || "Development";
switch (tutorialType) {
case "environment-setup":
return patterns.commonTools?.length > 0
? `Setting Up Your ${language} Development Environment`
: `Development Environment Setup for ${projectName}`;
default:
return `${tutorialType} Tutorial for ${projectName}`;
}
}
// Enhanced content generation methods with memory insights
private generateMemoryInformedGettingStartedContent(
analysis: any,
_memoryInsights: any,
): string {
const projectName = analysis.metadata?.projectName || "the project";
const language = analysis.metadata?.primaryLanguage || "development";
const patterns = _memoryInsights?.patterns || {};
const similarProjects = _memoryInsights?.similarProjects || [];
// Extract real project structure and dependencies
const realDependencies = analysis.dependencies?.packages || [];
const hasTests = analysis.structure?.hasTests;
const hasCI = analysis.structure?.hasCI;
const ecosystem = analysis.metadata?.ecosystem || "Node.js";
// Build getting started content based on actual project characteristics
let content = `# Getting Started with ${projectName}\n\n`;
if (similarProjects.length > 0) {
content += `Welcome to ${projectName}! This tutorial leverages successful patterns from ${similarProjects.length} similar ${language} projects to get you up and running quickly.\n\n`;
} else {
content += `Welcome to ${projectName}! This tutorial will guide you through setting up and running the project.\n\n`;
}
// Prerequisites based on actual analysis
content += `## Prerequisites\n\n`;
content += `Based on the project analysis, you'll need:\n\n`;
if (
ecosystem === "Node.js" ||
language === "TypeScript" ||
language === "JavaScript"
) {
const recommendedVersion =
this.getRecommendedNodeVersion(similarProjects);
content += `- Node.js (version ${recommendedVersion} or higher)\n`;
content += `- npm or yarn package manager\n`;
}
if (language === "TypeScript") {
content += `- TypeScript (globally installed or via npx)\n`;
}
content += `- Git for version control\n\n`;
// Installation based on real dependencies
content += `## Installation\n\n`;
content += `1. Clone the repository:\n`;
content += ` \`\`\`bash\n`;
content += ` git clone <repository-url>\n`;
content += ` cd ${projectName}\n`;
content += ` \`\`\`\n\n`;
content += `2. Install dependencies:\n`;
content += ` \`\`\`bash\n`;
if (realDependencies.includes("yarn")) {
content += ` yarn install\n`;
} else {
content += ` npm install\n`;
}
content += ` \`\`\`\n\n`;
// Real environment setup
if (this.projectHasEnvFile(analysis)) {
content += `3. Set up environment variables:\n`;
content += ` \`\`\`bash\n`;
content += ` cp .env.example .env\n`;
content += ` \`\`\`\n\n`;
}
// Running based on actual project setup
content += `## Running the Project\n\n`;
const runCommands = this.extractActualRunCommands(analysis);
if (runCommands.length > 0) {
runCommands.forEach((cmd) => {
content += `\`\`\`bash\n${cmd}\n\`\`\`\n\n`;
});
} else {
content += `\`\`\`bash\nnpm start\n\`\`\`\n\n`;
}
// Testing section based on actual test setup
if (hasTests) {
content += `## Verifying Your Setup\n\n`;
content += `Run the test suite to ensure everything is working:\n`;
content += `\`\`\`bash\n`;
const testFramework = this.detectTestFramework(analysis);
if (testFramework) {
content += `npm test # Uses ${testFramework}\n`;
} else {
content += `npm test\n`;
}
content += `\`\`\`\n\n`;
}
// Next steps based on memory insights
content += `## Next Steps\n\n`;
if (patterns.documentationStructures) {
content += `- Explore the [Architecture Overview](../explanation/architecture.md)\n`;
content += `- Learn about [Adding New Features](../how-to/add-feature.md)\n`;
}
if (hasCI) {
content += `- Check the [Deployment Guide](../how-to/deploy.md)\n`;
}
content += `- Review the [API Reference](../reference/api.md)\n`;
return content;
}
private generateMemoryInformedGettingStartedExamples(
analysis: any,
_memoryInsights: any,
): string[] {
const examples: string[] = [];
// Generate real usage example based on actual entry points
const entryPoint = this.findProjectEntryPoint(analysis);
if (entryPoint) {
examples.push(
`// Example: Basic usage\nimport { initialize } from './${entryPoint}';\n\nconst app = initialize({\n // Configuration options\n});\n\napp.start();`,
);
}
// TypeScript config example if project uses TypeScript
if (analysis.metadata?.primaryLanguage === "TypeScript") {
const actualTsConfig = this.extractTsConfigPatterns(analysis);
examples.push(
`// TypeScript configuration\n${JSON.stringify(
actualTsConfig,
null,
2,
)}`,
);
}
// Real package.json scripts
const scripts = this.extractPackageScripts(analysis);
if (scripts && Object.keys(scripts).length > 0) {
examples.push(
`// Available scripts\n${JSON.stringify({ scripts }, null, 2)}`,
);
}
return examples;
}
private getRecommendedNodeVersion(similarProjects: any[]): string {
const versions = similarProjects
.map((p) => p.content?.versions?.node)
.filter(Boolean);
if (versions.length > 0) {
// Return most common version
const versionCounts = versions.reduce(
(acc, v) => {
acc[v] = (acc[v] || 0) + 1;
return acc;
},
{} as Record<string, number>,
);
const mostCommon = Object.entries(versionCounts).sort(
([, a], [, b]) => (b as number) - (a as number),
)[0];
return mostCommon ? mostCommon[0] : "18";
}
return "18"; // Default modern version
}
private projectHasEnvFile(analysis: any): boolean {
const files = analysis.files || [];
return files.some(
(f: any) =>
f.name === ".env.example" ||
f.name === ".env.template" ||
f.name === "env.example",
);
}
private extractActualRunCommands(analysis: any): string[] {
const packageJson = this.findPackageJson(analysis);
if (packageJson?.scripts) {
const scripts = packageJson.scripts;
const runCommands = [];
if (scripts.dev) runCommands.push("npm run dev");
else if (scripts.start) runCommands.push("npm start");
else if (scripts.serve) runCommands.push("npm run serve");
return runCommands;
}
return [];
}
private detectTestFramework(analysis: any): string | null {
const dependencies = analysis.dependencies?.packages || [];
if (dependencies.includes("jest")) return "Jest";
if (dependencies.includes("mocha")) return "Mocha";
if (dependencies.includes("vitest")) return "Vitest";
if (dependencies.includes("jasmine")) return "Jasmine";
return null;
}
private findProjectEntryPoint(analysis: any): string | null {
const packageJson = this.findPackageJson(analysis);
if (packageJson?.main) {
return packageJson.main.replace(/\.(js|ts)$/, "");
}
// Look for common entry points
const files = analysis.files || [];
const entryPoints = ["index", "main", "app", "server"];
for (const entry of entryPoints) {
if (
files.some(
(f: any) => f.name === `${entry}.ts` || f.name === `${entry}.js`,
)
) {
return entry;
}
}
return null;
}
private findPackageJson(analysis: any): any {
const files = analysis.files || [];
const packageFile = files.find((f: any) => f.name === "package.json");
if (packageFile?.content) {
try {
return JSON.parse(packageFile.content);
} catch {
return null;
}
}
return null;
}
private extractTsConfigPatterns(analysis: any): any {
const files = analysis.files || [];
const tsConfigFile = files.find((f: any) => f.name === "tsconfig.json");
if (tsConfigFile?.content) {
try {
return JSON.parse(tsConfigFile.content);
} catch {
// Return sensible defaults based on project analysis
return {
compilerOptions: {
target: "ES2020",
module: "commonjs",
strict: true,
esModuleInterop: true,
skipLibCheck: true,
forceConsistentCasingInFileNames: true,
},
};
}
}
return null;
}
private extractPackageScripts(analysis: any): any {
const packageJson = this.findPackageJson(analysis);
return packageJson?.scripts || null;
}
// Content generation methods (keeping original structure but with memory enhancement)
private generateGettingStartedContent(_analysis: any): string {
return `# Getting Started with ${_analysis.metadata.projectName}
Welcome to ${_analysis.metadata.projectName}! This tutorial will guide you through setting up and running the project for the first time.
## Prerequisites
Before you begin, ensure you have the following installed:
- Node.js (version 18 or higher)
- npm or yarn package manager
- Git for version control
## Installation
1. Clone the repository:
\`\`\`bash
git clone <repository-url>
cd ${_analysis.metadata.projectName}
\`\`\`
2. Install dependencies:
\`\`\`bash
npm install
\`\`\`
3. Set up environment variables:
\`\`\`bash
cp .env.example .env
\`\`\`
## Running the Project
Start the development server:
\`\`\`bash
npm run dev
\`\`\`
## Verifying Your Setup
Run the test suite to ensure everything is working:
\`\`\`bash
npm test
\`\`\`
## Next Steps
- Explore the [Architecture Overview](../explanation/architecture.md)
- Learn about [Adding New Features](../how-to/add-feature.md)
- Check the [API Reference](../reference/api.md)
`;
}
private generateGettingStartedExamples(_analysis: any): string[] {
return [
`// Example: Basic usage
import { initialize } from './${_analysis.metadata.projectName}';
const app = initialize({
// Configuration options
});
app.start();`,
`// Example: TypeScript configuration
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}`,
];
}
private generateNodeSetupContent(_analysis: any): string {
return `# Setting Up Your Development Environment
This guide will help you configure a complete Node.js and TypeScript development environment.
## Installing Node.js
### Using Node Version Manager (nvm)
1. Install nvm:
\`\`\`bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
\`\`\`
2. Install and use the correct Node.js version:
\`\`\`bash
nvm install 18
nvm use 18
\`\`\`
## TypeScript Setup
1. Install TypeScript globally:
\`\`\`bash
npm install -g typescript
\`\`\`
2. Initialize TypeScript configuration:
\`\`\`bash
npx tsc --init
\`\`\`
## Development Tools
### Recommended VS Code Extensions
- ESLint
- Prettier
- TypeScript and JavaScript Language Features
- GitLens
### Debugging Configuration
Create a \`.vscode/launch.json\` file:
\`\`\`json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug TypeScript",
"skipFiles": ["<node_internals>/**"],
"program": "\${workspaceFolder}/src/index.ts",
"preLaunchTask": "tsc: build - tsconfig.json",
"outFiles": ["\${workspaceFolder}/dist/**/*.js"]
}
]
}
\`\`\`
`;
}
private generateNodeSetupExamples(): string[] {
return [
`// package.json scripts
{
"scripts": {
"dev": "ts-node-dev --respawn src/index.ts",
"build": "tsc",
"start": "node dist/index.js",
"test": "jest",
"lint": "eslint src --ext .ts"
}
}`,
];
}
private generateTestingTutorialContent(_analysis: any): string {
const testFramework = _analysis.technologies.testing?.[0] || "Jest";
return `# Writing and Running Tests
Learn how to write effective tests for your ${_analysis.metadata.projectName} code using ${testFramework}.
## Test Structure
Tests should follow the AAA pattern:
- **Arrange**: Set up test data and conditions
- **Act**: Execute the code being tested
- **Assert**: Verify the results
## Writing Your First Test
Create a test file with the \`.test.ts\` extension:
\`\`\`typescript
// example.test.ts
describe('Example Module', () => {
it('should perform expected behavior', () => {
// Arrange
const input = 'test';
// Act
const result = exampleFunction(input);
// Assert
expect(result).toBe('expected output');
});
});
\`\`\`
## Running Tests
Execute all tests:
\`\`\`bash
npm test
\`\`\`
Run tests in watch mode:
\`\`\`bash
npm test -- --watch
\`\`\`
## Test Coverage
Generate a coverage report:
\`\`\`bash
npm test -- --coverage
\`\`\`
## Best Practices
1. **Test behavior, not implementation**: Focus on what the code does, not how
2. **Keep tests simple**: Each test should verify one thing
3. **Use descriptive names**: Test names should explain what is being tested
4. **Maintain test independence**: Tests should not depend on each other
`;
}
private generateTestingExamples(_analysis: any): string[] {
return [
`// Unit test example
import { calculateTotal } from './calculator';
describe('Calculator', () => {
describe('calculateTotal', () => {
it('should sum all numbers correctly', () => {
const numbers = [1, 2, 3, 4, 5];
const result = calculateTotal(numbers);
expect(result).toBe(15);
});
it('should handle empty arrays', () => {
const result = calculateTotal([]);
expect(result).toBe(0);
});
it('should handle negative numbers', () => {
const numbers = [-1, -2, 3];
const result = calculateTotal(numbers);
expect(result).toBe(0);
});
});
});`,
`// Integration test example
import request from 'supertest';
import { app } from './app';
describe('API Endpoints', () => {
describe('GET /api/health', () => {
it('should return health status', async () => {
const response = await request(app)
.get('/api/health')
.expect(200);
expect(response.body).toEqual({
status: 'healthy',
timestamp: expect.any(String)
});
});
});
});`,
];
}
private generateFeatureGuideContent(_analysis: any): string {
return `# How to Add a New Feature
This guide walks you through the process of adding a new feature to ${_analysis.metadata.projectName}.
## Step 1: Plan Your Feature
Before writing code:
1. Define the feature requirements
2. Consider the impact on existing functionality
3. Plan the implementation approach
## Step 2: Create a Feature Branch
\`\`\`bash
git checkout -b feature/your-feature-name
\`\`\`
## Step 3: Implement the Feature
1. Write the core functionality
2. Add appropriate error handling
3. Include logging for debugging
## Step 4: Write Tests
Create tests for your new feature:
- Unit tests for individual functions
- Integration tests for feature workflows
- Edge case testing
## Step 5: Update Documentation
- Add API documentation if applicable
- Update user guides
- Include code examples
## Step 6: Submit for Review
1. Push your branch:
\`\`\`bash
git push origin feature/your-feature-name
\`\`\`
2. Create a pull request
3. Address review feedback
## Best Practices
- Keep changes focused and atomic
- Follow existing code patterns
- Maintain backward compatibility
- Consider performance implications
`;
}
private generateDebuggingGuideContent(_analysis: any): string {
return `# How to Debug Common Issues
This guide helps you troubleshoot and debug common issues in ${_analysis.metadata.projectName}.
## Debugging Tools
### Using the Built-in Debugger
1. Set breakpoints in your code
2. Run with debugging enabled:
\`\`\`bash
node --inspect src/index.js
\`\`\`
3. Connect your debugger (VS Code, Chrome DevTools, etc.)
### Logging
Enable verbose logging:
\`\`\`bash
DEBUG=* npm start
\`\`\`
## Common Issues and Solutions
### Issue: Module Not Found
**Symptoms**: Error message "Cannot find module"
**Solutions**:
1. Check if dependencies are installed: \`npm install\`
2. Verify import paths are correct
3. Check TypeScript path mappings in tsconfig.json
### Issue: Type Errors
**Symptoms**: TypeScript compilation errors
**Solutions**:
1. Run type checking: \`npm run typecheck\`
2. Update type definitions: \`npm install @types/package-name\`
3. Check for version mismatches
### Issue: Test Failures
**Symptoms**: Tests failing unexpectedly
**Solutions**:
1. Run tests in isolation
2. Check for race conditions
3. Verify test data setup
## Performance Debugging
### Memory Leaks
Use heap snapshots:
\`\`\`bash
node --expose-gc --inspect src/index.js
\`\`\`
### Slow Performance
Profile your application:
\`\`\`bash
node --prof src/index.js
\`\`\`
## Getting Help
If you're still stuck:
1. Check the [FAQ](../reference/faq.md)
2. Search existing issues on GitHub
3. Ask in the community forum
`;
}
private generateDeploymentGuideContent(_analysis: any): string {
return `# How to Deploy Your Application
This guide covers deployment options and best practices for ${_analysis.metadata.projectName}.
## Pre-Deployment Checklist
- [ ] All tests passing
- [ ] Environment variables configured
- [ ] Production dependencies installed
- [ ] Build process successful
- [ ] Security vulnerabilities addressed
## Deployment Options
### Option 1: GitHub Pages (Static Sites)
1. Build your application:
\`\`\`bash
npm run build
\`\`\`
2. Deploy to GitHub Pages:
\`\`\`bash
npm run deploy
\`\`\`
### Option 2: Cloud Platforms
#### Vercel
\`\`\`bash
vercel --prod
\`\`\`
#### Netlify
\`\`\`bash
netlify deploy --prod
\`\`\`
#### Heroku
\`\`\`bash
git push heroku main
\`\`\`
### Option 3: Docker Container
1. Build the Docker image:
\`\`\`bash
docker build -t ${_analysis.metadata.projectName} .
\`\`\`
2. Run the container:
\`\`\`bash
docker run -p 3000:3000 ${_analysis.metadata.projectName}
\`\`\`
## Continuous Deployment
### GitHub Actions
Create \`.github/workflows/deploy.yml\`:
\`\`\`yaml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- run: npm ci
- run: npm run build
- run: npm run deploy
\`\`\`
## Post-Deployment
1. Verify deployment success
2. Run smoke tests
3. Monitor application logs
4. Check performance metrics
`;
}
private generateAPIReference(analysis: any): string {
return `# API Reference
Complete reference for ${analysis.metadata.projectName} APIs.
## Core APIs
### initialize(options)
Initialize the application with the given options.
**Parameters:**
- \`options\` (Object): Configuration options
- \`port\` (number): Server port (default: 3000)
- \`host\` (string): Server host (default: 'localhost')
- \`debug\` (boolean): Enable debug mode (default: false)
**Returns:**
- \`Application\`: Application instance
**Example:**
\`\`\`typescript
const app = initialize({
port: 8080,
debug: true
});
\`\`\`
### start()
Start the application server.
**Returns:**
- \`Promise<void>\`: Resolves when server is running
**Example:**
\`\`\`typescript
await app.start();
console.log('Server running');
\`\`\`
### stop()
Stop the application server.
**Returns:**
- \`Promise<void>\`: Resolves when server is stopped
**Example:**
\`\`\`typescript
await app.stop();
console.log('Server stopped');
\`\`\`
## Events
### 'ready'
Emitted when the application is ready to accept connections.
\`\`\`typescript
app.on('ready', () => {
console.log('Application ready');
});
\`\`\`
### 'error'
Emitted when an error occurs.
\`\`\`typescript
app.on('error', (error) => {
console.error('Application error:', error);
});
\`\`\`
## Error Codes
| Code | Description |
|------|-------------|
| ERR_INVALID_CONFIG | Invalid configuration provided |
| ERR_PORT_IN_USE | Specified port is already in use |
| ERR_STARTUP_FAILED | Application failed to start |
`;
}
private generateConfigReference(analysis: any): string {
return `# Configuration Reference
Complete guide to configuring ${analysis.metadata.projectName}.
## Configuration File
Configuration can be provided via:
1. Environment variables
2. Configuration file (config.json)
3. Command-line arguments
## Configuration Options
### Server Configuration
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| \`server.port\` | number | 3000 | Server port |
| \`server.host\` | string | 'localhost' | Server host |
| \`server.timeout\` | number | 30000 | Request timeout (ms) |
### Database Configuration
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| \`database.host\` | string | 'localhost' | Database host |
| \`database.port\` | number | 5432 | Database port |
| \`database.name\` | string | 'myapp' | Database name |
| \`database.pool.min\` | number | 2 | Minimum pool connections |
| \`database.pool.max\` | number | 10 | Maximum pool connections |
### Logging Configuration
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| \`logging.level\` | string | 'info' | Log level (debug, info, warn, error) |
| \`logging.format\` | string | 'json' | Log format (json, text) |
| \`logging.destination\` | string | 'stdout' | Log destination |
## Environment Variables
All configuration options can be set via environment variables:
\`\`\`bash
# Server
PORT=8080
HOST=0.0.0.0
# Database
DATABASE_URL=postgresql://user:pass@localhost:5432/myapp
# Logging
LOG_LEVEL=debug
\`\`\`
## Configuration File Example
\`\`\`json
{
"server": {
"port": 3000,
"host": "localhost"
},
"database": {
"host": "localhost",
"port": 5432,
"name": "myapp"
},
"logging": {
"level": "info",
"format": "json"
}
}
\`\`\`
`;
}
private generateCLIReference(analysis: any): string {
return `# Command Line Interface
Reference for ${analysis.metadata.projectName} CLI commands.
## Global Options
| Option | Description |
|--------|-------------|
| \`--help, -h\` | Show help information |
| \`--version, -v\` | Show version number |
| \`--verbose\` | Enable verbose output |
| \`--quiet\` | Suppress non-error output |
## Commands
### start
Start the application.
\`\`\`bash
${analysis.metadata.projectName} start [options]
\`\`\`
**Options:**
- \`--port, -p <port>\`: Server port (default: 3000)
- \`--host, -h <host>\`: Server host (default: localhost)
- \`--config, -c <file>\`: Configuration file path
### build
Build the application for production.
\`\`\`bash
${analysis.metadata.projectName} build [options]
\`\`\`
**Options:**
- \`--output, -o <dir>\`: Output directory (default: dist)
- \`--minify\`: Minify output
- \`--sourcemap\`: Generate source maps
### test
Run tests.
\`\`\`bash
${analysis.metadata.projectName} test [options]
\`\`\`
**Options:**
- \`--watch, -w\`: Run in watch mode
- \`--coverage\`: Generate coverage report
- \`--bail\`: Stop on first test failure
### lint
Run linting checks.
\`\`\`bash
${analysis.metadata.projectName} lint [options]
\`\`\`
**Options:**
- \`--fix\`: Automatically fix issues
- \`--format <format>\`: Output format (stylish, json, compact)
## Examples
### Starting with custom configuration
\`\`\`bash
${analysis.metadata.projectName} start --config production.json --port 8080
\`\`\`
### Running tests with coverage
\`\`\`bash
${analysis.metadata.projectName} test --coverage --watch
\`\`\`
### Building for production
\`\`\`bash
${analysis.metadata.projectName} build --minify --output ./production
\`\`\`
`;
}
private generateArchitectureContent(_analysis: any): string {
return `# Architecture Overview
Understanding the architecture of ${_analysis.metadata.projectName}.
## System Architecture
${_analysis.metadata.projectName} follows a modular architecture designed for scalability and maintainability.
### Core Components
1. **Core Engine**: The main processing engine that handles all operations
2. **Plugin System**: Extensible plugin architecture for custom functionality
3. **API Layer**: RESTful API for external integrations
4. **Data Layer**: Abstracted data access layer
## Design Principles
### Separation of Concerns
Each module has a single, well-defined responsibility:
- Business logic is separated from presentation
- Data access is abstracted from business logic
- External dependencies are isolated
### Dependency Injection
Dependencies are injected rather than hard-coded:
- Improves testability
- Enables easier mocking
- Supports multiple implementations
### Event-Driven Architecture
Components communicate through events:
- Loose coupling between modules
- Asynchronous processing capabilities
- Scalable message handling
## Directory Structure
\`\`\`
${_analysis.metadata.projectName}/
├── src/
│ ├── core/ # Core functionality
│ ├── plugins/ # Plugin implementations
│ ├── api/ # API endpoints
│ ├── services/ # Business services
│ ├── models/ # Data models
│ └── utils/ # Utility functions
├── tests/ # Test files
├── docs/ # Documentation
└── config/ # Configuration files
\`\`\`
## Data Flow
1. **Request Reception**: API receives incoming requests
2. **Validation**: Input validation and sanitization
3. **Processing**: Business logic execution
4. **Data Access**: Database operations if needed
5. **Response Generation**: Format and return response
## Scalability Considerations
### Horizontal Scaling
The application supports horizontal scaling through:
- Stateless design
- Load balancer compatibility
- Distributed caching support
### Performance Optimization
- Lazy loading of modules
- Caching strategies
- Database connection pooling
- Asynchronous operations
## Security Architecture
### Authentication & Authorization
- JWT-based authentication
- Role-based access control (RBAC)
- API key management
### Data Protection
- Encryption at rest and in transit
- Input validation and sanitization
- SQL injection prevention
- XSS protection
`;
}
private generateDesignDecisionsContent(_analysis: any): string {
return `# Design Decisions
Key architectural and design decisions made in ${_analysis.metadata.projectName}.
## Technology Stack
### Why ${_analysis.metadata.primaryLanguage}?
We chose ${_analysis.metadata.primaryLanguage} for:
- Strong type safety
- Excellent tooling support
- Large ecosystem of libraries
- Good performance characteristics
- Team familiarity
### Framework Selection
After evaluating multiple options, we selected our current stack based on:
- Community support and documentation
- Performance benchmarks
- Learning curve for new developers
- Long-term maintenance considerations
## Architectural Patterns
### Repository Pattern
We implement the repository pattern for data access:
- **Benefit**: Abstracts data source details
- **Trade-off**: Additional abstraction layer
- **Rationale**: Enables easy switching between data sources
### Service Layer
Business logic is encapsulated in services:
- **Benefit**: Reusable business logic
- **Trade-off**: More files and complexity
- **Rationale**: Clear separation of concerns
### Dependency Injection
We use dependency injection throughout:
- **Benefit**: Improved testability and flexibility
- **Trade-off**: Initial setup complexity
- **Rationale**: Essential for large-scale applications
## API Design
### RESTful vs GraphQL
We chose REST because:
- Simpler to implement and understand
- Better caching strategies
- Fits our use case well
- Lower operational complexity
### Versioning Strategy
API versioning through URL paths:
- **Format**: /api/v1/resource
- **Benefit**: Clear version boundaries
- **Trade-off**: URL complexity
- **Rationale**: Industry standard approach
## Database Decisions
### SQL vs NoSQL
We use SQL for:
- ACID compliance requirements
- Complex relational data
- Mature tooling and expertise
- Predictable performance
### Migration Strategy
Database migrations are managed through:
- Version-controlled migration files
- Automated migration on deployment
- Rollback capabilities
- Data validation steps
## Testing Strategy
### Test Pyramid
Our testing approach follows the test pyramid:
- Many unit tests (fast, isolated)
- Some integration tests (component interaction)
- Few E2E tests (full system validation)
### Coverage Goals
- Unit test coverage: 80% minimum
- Critical path coverage: 100%
- Integration test coverage: Key workflows
## Performance Decisions
### Caching Strategy
Multi-level caching approach:
- Application-level caching
- Database query caching
- CDN for static assets
- Redis for session data
### Async Processing
Background jobs for:
- Email sending
- Report generation
- Data processing
- Third-party integrations
## Security Decisions
### Authentication Method
JWT tokens because:
- Stateless authentication
- Scalable across services
- Standard implementation
- Good library support
### Data Encryption
- Passwords: bcrypt with salt rounds
- Sensitive data: AES-256 encryption
- Communications: TLS 1.3
- Secrets: Environment variables
## Future Considerations
### Microservices
Currently monolithic, but designed for potential splitting:
- Clear module boundaries
- Service-oriented architecture
- Database per service capability
- API gateway ready
### Cloud Native
Prepared for cloud deployment:
- 12-factor app principles
- Container-ready architecture
- Environment-based configuration
- Stateless design
`;
}
private generateTechnologyStackContent(_analysis: any): string {
return `# Technology Stack
Complete overview of technologies used in ${_analysis.metadata.projectName}.
## Core Technologies
### Runtime & Language
- **${_analysis.metadata.primaryLanguage}**: Primary development language
- **${_analysis.metadata.ecosystem}**: Runtime environment
- **TypeScript**: Type-safe JavaScript development
### Package Management
- **npm/yarn**: Dependency management
- **npx**: Package execution
- **nvm**: Node version management
## Development Tools
### Build Tools
- **TypeScript Compiler**: Transpilation to JavaScript
- **Webpack/Rollup**: Module bundling
- **Babel**: JavaScript transformation
### Code Quality
- **ESLint**: Code linting
- **Prettier**: Code formatting
- **Husky**: Git hooks
- **lint-staged**: Pre-commit checks
### Testing
${
_analysis.technologies.testing
?.map((t: string) => `- **${t}**: Testing framework`)
.join("\\n") || "- **Jest**: Testing framework"
}
- **Supertest**: API testing
- **Coverage tools**: Code coverage reporting
## Infrastructure
### Version Control
- **Git**: Source control
- **GitHub**: Repository hosting
- **GitHub Actions**: CI/CD pipelines
### Deployment
${
_analysis.technologies.deployment
?.map((t: string) => `- **${t}**: Deployment platform`)
.join("\\n") || "- **Docker**: Containerization"
}
- **GitHub Pages**: Documentation hosting
### Monitoring
- **Application logs**: Custom logging
- **Error tracking**: Error monitoring
- **Performance monitoring**: APM tools
## Dependencies
### Core Dependencies
\`\`\`json
${JSON.stringify(_analysis.dependencies.packages?.slice(0, 5) || [], null, 2)}
\`\`\`
### Development Dependencies
- Testing frameworks
- Build tools
- Linting tools
- Type definitions
## Database & Storage
${
_analysis.technologies.database
? `### Database
- **${_analysis.technologies.database}**: Primary database
- **Migration tools**: Database versioning
- **ORMs/Query builders**: Data access layer`
: `### Storage
- File system for local development
- Cloud storage for production
- Caching layers for performance`
}
## External Services
### Third-party APIs
- Authentication services
- Payment processing
- Email services
- Analytics
### Cloud Services
- Hosting platforms
- CDN services
- Backup solutions
- Monitoring services
## Security Tools
### Development Security
- **Dependency scanning**: npm audit
- **Secret management**: Environment variables
- **Security headers**: Helmet.js
- **Input validation**: Sanitization libraries
### Production Security
- **TLS/SSL**: Encrypted communications
- **WAF**: Web application firewall
- **DDoS protection**: Rate limiting
- **Access control**: Authentication/authorization
## Documentation Tools
### Documentation Generation
- **Markdown**: Documentation format
- **Static site generators**: Documentation hosting
- **API documentation**: OpenAPI/Swagger
- **Code documentation**: JSDoc/TypeDoc
## Development Environment
### Recommended IDE
- **VS Code**: Primary development environment
- **Extensions**: Language support, debugging
- **Configuration**: Shared team settings
### Local Development
- **Hot reloading**: Development server
- **Debugging tools**: Chrome DevTools, VS Code debugger
- **Database tools**: Local database management
- **API testing**: Postman/Insomnia
## Upgrade Path
### Version Management
- Regular dependency updates
- Security patch monitoring
- Breaking change management
- Deprecation handling
### Future Technologies
- Considering adoption of:
- New framework versions
- Performance improvements
- Developer experience enhancements
- Security improvements
`;
}
private async generateTutorialContent(
tutorials: any[],
_analysis: any,
): Promise<any[]> {
// Transform tutorial plans into actual content
return tutorials;
}
private async generateHowToContent(
howTos: any[],
_analysis: any,
): Promise<any[]> {
return howTos;
}
private async generateReferenceContent(
reference: any[],
_analysis: any,
): Promise<any[]> {
return reference;
}
private async generateExplanationContent(
explanation: any[],
_analysis: any,
): Promise<any[]> {
return explanation;
}
private async writeContentToStructure(
docsPath: string,
content: any,
preserveExisting: boolean,
): Promise<number> {
let filesCreated = 0;
// Create directory structure if it doesn't exist
const dirs = ["tutorials", "how-to", "reference", "explanation"];
for (const dir of dirs) {
const dirPath = path.join(docsPath, dir);
await fs.mkdir(dirPath, { recursive: true });
}
// Write tutorial content
for (const tutorial of content.tutorials) {
const fileName = this.slugify(tutorial.title) + ".md";
const filePath = path.join(docsPath, "tutorials", fileName);
if (preserveExisting) {
try {
await fs.access(filePath);
continue; // Skip if file exists
} catch {
// File doesn't exist, proceed to write
}
}
await fs.writeFile(filePath, tutorial.content, "utf-8");
filesCreated++;
}
// Write how-to guides
for (const howTo of content.howTos) {
const fileName = this.slugify(howTo.title) + ".md";
const filePath = path.join(docsPath, "how-to", fileName);
if (preserveExisting) {
try {
await fs.access(filePath);
continue;
} catch {
// File doesn't exist, proceed with creation
}
}
await fs.writeFile(filePath, howTo.content, "utf-8");
filesCreated++;
}
// Write reference documentation
for (const ref of content.reference) {
const fileName = this.slugify(ref.title) + ".md";
const filePath = path.join(docsPath, "reference", fileName);
if (preserveExisting) {
try {
await fs.access(filePath);
continue;
} catch {
// File doesn't exist, proceed with creation
}
}
await fs.writeFile(filePath, ref.content, "utf-8");
filesCreated++;
}
// Write explanation content
for (const exp of content.explanation) {
const fileName = this.slugify(exp.title) + ".md";
const filePath = path.join(docsPath, "explanation", fileName);
if (preserveExisting) {
try {
await fs.access(filePath);
continue;
} catch {
// File doesn't exist, proceed with creation
}
}
await fs.writeFile(filePath, exp.content, "utf-8");
filesCreated++;
}
return filesCreated;
}
private async updateNavigationAndCrossReferences(
docsPath: string,
contentPlan: ContentPlan,
): Promise<void> {
// Create main index file with navigation
const indexContent = `# Documentation
Welcome to the documentation! This comprehensive guide is organized following the Diataxis framework.
## 📚 Learning-Oriented: Tutorials
Start here if you're new to the project:
${contentPlan.tutorials
.map((t) => `- [${t.title}](tutorials/${this.slugify(t.title)}.md)`)
.join("\\n")}
## 🔧 Task-Oriented: How-To Guides
Practical guides for specific tasks:
${contentPlan.howToGuides
.map((h) => `- [${h.title}](how-to/${this.slugify(h.title)}.md)`)
.join("\\n")}
## 📖 Information-Oriented: Reference
Detailed technical reference:
${contentPlan.reference
.map((r) => `- [${r.title}](reference/${this.slugify(r.title)}.md)`)
.join("\\n")}
## 💡 Understanding-Oriented: Explanation
Conceptual documentation and background:
${contentPlan.explanation
.map((e) => `- [${e.title}](explanation/${this.slugify(e.title)}.md)`)
.join("\\n")}
`;
await fs.writeFile(path.join(docsPath, "index.md"), indexContent, "utf-8");
}
private calculatePopulationMetrics(
filesCreated: number,
contentPlan: ContentPlan,
): any {
const totalPlanned =
contentPlan.tutorials.length +
contentPlan.howToGuides.length +
contentPlan.reference.length +
contentPlan.explanation.length;
return {
coverage: (filesCreated / totalPlanned) * 100,
completeness: 85, // Example metric
projectSpecificity: 75, // Example metric
};
}
private generateMemoryInformedNextSteps(
analysis: any,
_contentPlan: ContentPlan,
_memoryInsights: any,
): string[] {
const nextSteps = [];
const patterns = _memoryInsights?.patterns || {};
const _similarProjects = _memoryInsights?.similarProjects || [];
// Memory-informed next steps based on successful patterns
if (_similarProjects.length > 0) {
nextSteps.push(
`Review and customize the generated content (based on ${_similarProjects.length} similar project patterns)`,
);
} else {
nextSteps.push("Review and customize the generated content");
}
// Project-specific recommendations
if (analysis.structure?.hasTests) {
nextSteps.push("Run and validate all code examples and commands");
}
if (analysis.structure?.hasCI) {
nextSteps.push(
"Set up automated documentation deployment using successful CI patterns",
);
}
// Memory-informed improvements
if (patterns.documentationStructures) {
nextSteps.push(
"Enhance documentation structure based on successful similar projects",
);
}
if (patterns.deploymentStrategies) {
nextSteps.push(
"Implement proven deployment strategies from similar projects",
);
}
// Update sitemap after content population
nextSteps.push(
"Update sitemap.xml using manage_sitemap tool (action: update) to include new pages",
);
// Always include validation
nextSteps.push(
"Validate technical accuracy using project-specific analysis",
);
return nextSteps;
}
// Add the missing memory-informed content generation methods
private async generateMemoryInformedTutorialContent(
tutorials: any[],
analysis: any,
_memoryInsights: any,
): Promise<any[]> {
return tutorials.map((tutorial) => ({
...tutorial,
content: this.enhanceContentWithMemoryInsights(
tutorial.content,
analysis,
_memoryInsights,
),
codeExamples: this.enhanceExamplesWithRealCode(
tutorial.codeExamples || [],
analysis,
_memoryInsights,
),
}));
}
private async generateMemoryInformedHowToContent(
howTos: any[],
analysis: any,
_memoryInsights: any,
): Promise<any[]> {
return howTos.map((howTo) => ({
...howTo,
content: this.enhanceContentWithMemoryInsights(
howTo.content,
analysis,
_memoryInsights,
),
}));
}
private async generateMemoryInformedReferenceContent(
reference: any[],
analysis: any,
_memoryInsights: any,
): Promise<any[]> {
return reference.map((ref) => ({
...ref,
content: this.generateMemoryInformedAPIReference(
analysis,
_memoryInsights,
),
}));
}
private async generateMemoryInformedExplanationContent(
explanation: any[],
analysis: any,
_memoryInsights: any,
): Promise<any[]> {
return explanation.map((exp) => ({
...exp,
content: this.enhanceContentWithMemoryInsights(
exp.content,
analysis,
_memoryInsights,
),
}));
}
private enhanceContentWithMemoryInsights(
content: string,
analysis: any,
_memoryInsights: any,
): string {
// Replace generic placeholders with real project information
const language = analysis.metadata?.primaryLanguage || "development";
const similarCount = _memoryInsights?.similarProjects?.length || 0;
let enhancedContent = content;
// Add memory-informed context
if (similarCount > 0) {
enhancedContent = enhancedContent.replace(
/This guide/g,
`This guide (based on patterns from ${similarCount} similar ${language} projects)`,
);
}
// Replace generic examples with real ones
enhancedContent = this.replaceGenericExamplesWithReal(
enhancedContent,
analysis,
);
return enhancedContent;
}
private enhanceExamplesWithRealCode(
examples: string[],
analysis: any,
_memoryInsights: any,
): string[] {
return examples.map((example) => {
// Replace generic project names with actual project name
const projectName = analysis.metadata?.projectName || "project";
return example.replace(
/your-project|myproject|example-project/g,
projectName,
);
});
}
private generateMemoryInformedAPIReference(
analysis: any,
_memoryInsights: any,
): string {
// Extract actual API structure from project analysis
const entryPoint = this.findProjectEntryPoint(analysis);
const packageJson = this.findPackageJson(analysis);
const projectName = analysis.metadata?.projectName || "the project";
let content = `# API Reference\n\n`;
content += `Complete reference for ${projectName} APIs.\n\n`;
if (entryPoint) {
content += `## Core APIs\n\n`;
content += `### Entry Point: ${entryPoint}\n\n`;
content += `The main entry point for ${projectName}.\n\n`;
}
// Add real configuration if available
if (packageJson?.main) {
content += `**Main Module:** \`${packageJson.main}\`\n\n`;
}
// Add real scripts if available
const scripts = packageJson?.scripts;
if (scripts && Object.keys(scripts).length > 0) {
content += `## Available Scripts\n\n`;
Object.entries(scripts).forEach(([script, command]) => {
content += `### ${script}\n\n`;
content += `\`\`\`bash\nnpm run ${script}\n\`\`\`\n\n`;
content += `Runs: \`${command}\`\n\n`;
});
}
return content;
}
private replaceGenericExamplesWithReal(
content: string,
analysis: any,
): string {
const projectName = analysis.metadata?.projectName || "project";
const language = analysis.metadata?.primaryLanguage || "JavaScript";
// Replace generic project references
content = content.replace(/your-project-name/g, projectName);
content = content.replace(/YourProject/g, projectName);
content = content.replace(/your-language/g, language);
// Replace generic ports with common defaults for the project type
const defaultPort = this.getDefaultPortForProject(analysis);
content = content.replace(/3000/g, defaultPort.toString());
return content;
}
private getDefaultPortForProject(analysis: any): number {
const packageJson = this.findPackageJson(analysis);
if (
packageJson?.scripts?.start &&
packageJson.scripts.start.includes("port")
) {
// Try to extract port from start script
const portMatch = packageJson.scripts.start.match(/port[:\s=](\d+)/i);
if (portMatch) {
return parseInt(portMatch[1], 10);
}
}
// Default ports based on project type
const dependencies = analysis.dependencies?.packages || [];
if (dependencies.includes("express")) return 3000;
if (dependencies.includes("fastify")) return 3000;
if (dependencies.includes("next")) return 3000;
if (dependencies.includes("gatsby")) return 8000;
if (dependencies.includes("nuxt")) return 3000;
return 3000; // Generic default
}
// Stub methods for the missing plan generation (to be implemented if needed)
private generateMemoryInformedHowToPlan(
analysis: any,
level: string,
_memoryInsights: any,
): any[] {
return this.generateHowToPlan(analysis, level);
}
private generateMemoryInformedReferencePlan(
analysis: any,
level: string,
_memoryInsights: any,
): any[] {
return this.generateReferencePlan(analysis, level);
}
private generateMemoryInformedExplanationPlan(
analysis: any,
level: string,
_memoryInsights: any,
): any[] {
return this.generateExplanationPlan(analysis, level);
}
private generateMemoryInformedNodeSetupContent(
_analysis: any,
_patterns: any,
): string {
return this.generateNodeSetupContent(_analysis);
}
private generateMemoryInformedNodeSetupExamples(
_analysis: any,
_patterns: any,
): string[] {
return this.generateNodeSetupExamples();
}
private generateNextSteps(
_analysis: any,
_contentPlan: ContentPlan,
): string[] {
return [
"Review and customize the generated content",
"Add project-specific examples and use cases",
"Validate technical accuracy of code examples",
"Add screenshots and diagrams where helpful",
"Test all commands and code snippets",
"Set up automated documentation deployment",
];
}
private slugify(text: string): string {
return text
.toLowerCase()
.replace(/[^\w\s-]/g, "")
.replace(/\s+/g, "-")
.replace(/--+/g, "-")
.trim();
}
// DevOps Detection Methods
private detectDevOpsTools(analysis: any): DevOpsToolProfile {
return {
containerization: this.detectContainerization(analysis),
orchestration: this.detectOrchestration(analysis),
cicd: this.detectCICD(analysis),
configuration: this.detectConfigManagement(analysis),
monitoring: this.detectMonitoring(analysis),
security: this.detectSecurity(analysis),
};
}
private detectContainerization(analysis: any): ContainerTechnology[] {
const detected: ContainerTechnology[] = [];
const files = analysis.files || [];
// Docker detection
if (
files.some((f: any) => f.name === "Dockerfile") ||
files.some((f: any) => f.name === "docker-compose.yml") ||
files.some((f: any) => f.name === "docker-compose.yaml")
) {
detected.push({
name: "docker",
version: this.extractDockerVersion(analysis),
configFiles: this.getDockerFiles(analysis),
usage: "containerization",
});
}
// Podman detection
if (
files.some((f: any) => f.name === "Containerfile") ||
files.some((f: any) => f.name === "podman-compose.yml")
) {
detected.push({
name: "podman",
configFiles: this.getPodmanFiles(analysis),
usage: "containerization",
});
}
return detected;
}
private detectOrchestration(analysis: any): OrchestrationTechnology[] {
const detected: OrchestrationTechnology[] = [];
const files = analysis.files || [];
// Kubernetes detection
if (
files.some(
(f: any) => f.path?.includes("k8s/") || f.path?.includes("kubernetes/"),
)
) {
detected.push({
name: "kubernetes",
manifests: this.getKubernetesManifests(analysis),
resources: this.analyzeKubernetesResources(analysis),
namespaces: this.extractNamespaces(analysis),
});
}
// OpenShift detection
if (
files.some((f: any) => f.path?.includes(".s2i/")) ||
this.hasFileContent(analysis, "kind: DeploymentConfig")
) {
detected.push({
name: "openshift",
});
}
return detected;
}
private detectCICD(analysis: any): CICDTechnology[] {
const detected: CICDTechnology[] = [];
const files = analysis.files || [];
// GitHub Actions detection
if (files.some((f: any) => f.path?.includes(".github/workflows/"))) {
detected.push({
name: "github-actions",
});
}
// Tekton detection
if (
files.some((f: any) => f.path?.includes(".tekton/")) ||
this.hasFileContent(analysis, "apiVersion: tekton.dev")
) {
detected.push({
name: "tekton",
});
}
return detected;
}
private detectConfigManagement(analysis: any): ConfigManagementTechnology[] {
const detected: ConfigManagementTechnology[] = [];
const files = analysis.files || [];
// Ansible detection
if (
files.some((f: any) => f.name === "ansible.cfg") ||
files.some((f: any) => f.path?.includes("playbooks/")) ||
files.some((f: any) => f.path?.includes("roles/"))
) {
detected.push({
name: "ansible",
playbooks: this.getAnsiblePlaybooks(analysis),
roles: this.getAnsibleRoles(analysis),
});
}
// Terraform detection
if (files.some((f: any) => f.name?.endsWith(".tf"))) {
detected.push({
name: "terraform",
});
}
return detected;
}
private detectMonitoring(analysis: any): MonitoringTechnology[] {
const detected: MonitoringTechnology[] = [];
if (this.hasFileContent(analysis, "prometheus")) {
detected.push({ name: "prometheus" });
}
if (this.hasFileContent(analysis, "grafana")) {
detected.push({ name: "grafana" });
}
return detected;
}
private detectSecurity(analysis: any): SecurityTechnology[] {
const detected: SecurityTechnology[] = [];
if (this.hasFileContent(analysis, "falco")) {
detected.push({ name: "falco" });
}
return detected;
}
// Python Framework Detection
private detectPythonFrameworks(analysis: any): any[] {
const frameworks: any[] = [];
const dependencies = analysis.dependencies?.packages || [];
if (dependencies.includes("django")) {
frameworks.push({ name: "django", type: "web-framework" });
}
if (dependencies.includes("fastapi")) {
frameworks.push({ name: "fastapi", type: "web-framework" });
}
if (dependencies.includes("flask")) {
frameworks.push({ name: "flask", type: "web-framework" });
}
return frameworks;
}
// Helper methods for file detection
private hasFileContent(analysis: any, content: string): boolean {
const files = analysis.files || [];
return files.some((f: any) => f.content?.includes(content));
}
private extractDockerVersion(_analysis: any): string | undefined {
return undefined; // Could be implemented to parse Dockerfile
}
private getDockerFiles(analysis: any): string[] {
const files = analysis.files || [];
return files
.filter(
(f: any) =>
f.name === "Dockerfile" || f.name.includes("docker-compose"),
)
.map((f: any) => f.name);
}
private getPodmanFiles(analysis: any): string[] {
const files = analysis.files || [];
return files
.filter(
(f: any) =>
f.name === "Containerfile" || f.name.includes("podman-compose"),
)
.map((f: any) => f.name);
}
private getKubernetesManifests(analysis: any): string[] {
const files = analysis.files || [];
return files
.filter(
(f: any) => f.path?.includes("k8s/") || f.path?.includes("kubernetes/"),
)
.map((f: any) => f.name);
}
private analyzeKubernetesResources(_analysis: any): string[] {
return ["Deployment", "Service", "ConfigMap"]; // Simplified
}
private extractNamespaces(_analysis: any): string[] {
return ["default"]; // Simplified
}
private getAnsiblePlaybooks(analysis: any): string[] {
const files = analysis.files || [];
return files
.filter(
(f: any) => f.path?.includes("playbooks/") && f.name?.endsWith(".yml"),
)
.map((f: any) => f.name);
}
private getAnsibleRoles(analysis: any): string[] {
const files = analysis.files || [];
return files
.filter((f: any) => f.path?.includes("roles/"))
.map((f: any) => f.name);
}
// Content generation methods for new features
private generateContainerTutorialContent(
_analysis: any,
_containerTech: ContainerTechnology,
): string {
return `# Containerizing ${_analysis.metadata.projectName} with ${
_containerTech.name
}
Learn how to package your ${
_analysis.metadata.primaryLanguage
} application into a container for consistent deployment across environments.
## Prerequisites
- ${_containerTech.name} installed on your system
- Basic understanding of containerization concepts
- Your application running locally
## Understanding Containerization
Containers provide a lightweight, portable way to package applications with all their dependencies. This ensures your application runs consistently across different environments.
## Creating a ${
_containerTech.name === "docker" ? "Dockerfile" : "Containerfile"
}
1. Create a ${
_containerTech.name === "docker" ? "Dockerfile" : "Containerfile"
} in your project root:
\`\`\`dockerfile
${this.generateContainerFileContent(_analysis, _containerTech)}
\`\`\`
## Building Your Container Image
\`\`\`bash
${_containerTech.name} build -t ${_analysis.metadata.projectName}:latest .
\`\`\`
## Running Your Container
\`\`\`bash
${_containerTech.name} run -p 3000:3000 ${_analysis.metadata.projectName}:latest
\`\`\`
## Best Practices
- Use multi-stage builds to reduce image size
- Don't run containers as root user
- Use .dockerignore to exclude unnecessary files
- Pin base image versions for reproducibility
## Next Steps
- Learn about container orchestration with Kubernetes
- Set up automated builds in CI/CD pipeline
- Implement health checks for production deployments
`;
}
private generateOrchestrationTutorialContent(
_analysis: any,
_orchestrationTech: OrchestrationTechnology,
): string {
return `# Deploying ${_analysis.metadata.projectName} to ${
_orchestrationTech.name
}
Deploy your containerized application to ${
_orchestrationTech.name
} for scalable, production-ready hosting.
## Prerequisites
- ${_orchestrationTech.name} cluster access
- kubectl CLI tool installed
- Container image built and pushed to registry
## Understanding ${_orchestrationTech.name}
${
_orchestrationTech.name
} is a container orchestration platform that automates deployment, scaling, and management of containerized applications.
## Creating Deployment Manifests
1. Create a deployment configuration:
\`\`\`yaml
${this.generateKubernetesManifest(_analysis, "deployment")}
\`\`\`
2. Create a service configuration:
\`\`\`yaml
${this.generateKubernetesManifest(_analysis, "service")}
\`\`\`
## Deploying to ${_orchestrationTech.name}
\`\`\`bash
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
\`\`\`
## Monitoring Your Deployment
\`\`\`bash
kubectl get pods
kubectl get services
kubectl logs -f deployment/${_analysis.metadata.projectName}
\`\`\`
## Scaling Your Application
\`\`\`bash
kubectl scale deployment ${_analysis.metadata.projectName} --replicas=3
\`\`\`
## Next Steps
- Set up ingress for external access
- Configure persistent storage
- Implement monitoring and logging
`;
}
private generatePythonEnvironmentContent(_analysis: any): string {
return `# Python Virtual Environment Setup
Set up an isolated Python development environment for ${_analysis.metadata.projectName}.
## Why Virtual Environments?
Virtual environments isolate project dependencies, preventing conflicts between different projects and ensuring reproducible builds.
## Creating a Virtual Environment
### Using venv (Python 3.3+)
\`\`\`bash
python -m venv venv
\`\`\`
### Using virtualenv
\`\`\`bash
pip install virtualenv
virtualenv venv
\`\`\`
### Using conda
\`\`\`bash
conda create --name ${_analysis.metadata.projectName} python=3.11
\`\`\`
## Activating the Environment
### Linux/macOS
\`\`\`bash
source venv/bin/activate
\`\`\`
### Windows
\`\`\`bash
venv\\Scripts\\activate
\`\`\`
### Conda
\`\`\`bash
conda activate ${_analysis.metadata.projectName}
\`\`\`
## Installing Dependencies
\`\`\`bash
pip install -r requirements.txt
\`\`\`
## Development Tools
Install useful development tools:
\`\`\`bash
pip install black flake8 pytest mypy
\`\`\`
## Deactivating the Environment
\`\`\`bash
deactivate
\`\`\`
## Best Practices
- Always use virtual environments for Python projects
- Keep requirements.txt updated
- Use requirements-dev.txt for development dependencies
- Consider using poetry or pipenv for advanced dependency management
`;
}
private generatePythonFrameworkTutorialContent(
_analysis: any,
framework: any,
): string {
if (framework.name === "django") {
return this.generateDjangoTutorialContent(_analysis);
} else if (framework.name === "fastapi") {
return this.generateFastAPITutorialContent(_analysis);
} else if (framework.name === "flask") {
return this.generateFlaskTutorialContent(_analysis);
}
return `# Building Applications with ${framework.name}
Learn how to build applications using ${framework.name}.
## Getting Started
Install ${framework.name}:
\`\`\`bash
pip install ${framework.name}
\`\`\`
## Basic Application Structure
Create your first ${framework.name} application and explore the framework's core concepts.
`;
}
private generateDjangoTutorialContent(_analysis: any): string {
return `# Building Applications with Django
Create robust web applications using Django's Model-View-Template architecture.
## Project Setup
1. Install Django:
\`\`\`bash
pip install django
\`\`\`
2. Create a new Django project:
\`\`\`bash
django-admin startproject ${_analysis.metadata.projectName}
cd ${_analysis.metadata.projectName}
\`\`\`
3. Create your first app:
\`\`\`bash
python manage.py startapp core
\`\`\`
## Understanding Django Architecture
Django follows the MTV (Model-View-Template) pattern:
- **Models**: Define your data structure
- **Views**: Handle business logic and user interactions
- **Templates**: Control presentation layer
## Creating Your First Model
\`\`\`python
# core/models.py
from django.db import models
class Item(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
\`\`\`
## Running Migrations
\`\`\`bash
python manage.py makemigrations
python manage.py migrate
\`\`\`
## Creating Views
\`\`\`python
# core/views.py
from django.shortcuts import render
from .models import Item
def item_list(request):
items = Item.objects.all()
return render(request, 'core/item_list.html', {'items': items})
\`\`\`
## URL Configuration
\`\`\`python
# core/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.item_list, name='item_list'),
]
\`\`\`
## Running the Development Server
\`\`\`bash
python manage.py runserver
\`\`\`
## Next Steps
- Learn about Django REST Framework for API development
- Explore Django's admin interface
- Implement user authentication
- Deploy with Gunicorn and PostgreSQL
`;
}
private generateFastAPITutorialContent(_analysis: any): string {
return `# Building APIs with FastAPI
Create modern, fast APIs with automatic documentation using FastAPI.
## Installation
\`\`\`bash
pip install fastapi uvicorn
\`\`\`
## Basic Application
\`\`\`python
# main.py
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.post("/items/")
async def create_item(item: Item):
return item
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
\`\`\`
## Running the Server
\`\`\`bash
uvicorn main:app --reload
\`\`\`
## Interactive Documentation
FastAPI automatically generates interactive API documentation:
- Swagger UI: http://127.0.0.1:8000/docs
- ReDoc: http://127.0.0.1:8000/redoc
## Key Features
- **Type Hints**: Python type hints for automatic validation
- **Async Support**: Native async/await support
- **Dependency Injection**: Powerful dependency injection system
- **Security**: Built-in security utilities
## Next Steps
- Add database integration with SQLAlchemy
- Implement authentication with JWT
- Add background tasks
- Deploy with Docker
`;
}
private generateFlaskTutorialContent(_analysis: any): string {
return `# Building Applications with Flask
Create lightweight web applications and APIs using Flask's minimalist approach.
## Installation
\`\`\`bash
pip install flask
\`\`\`
## Basic Application
\`\`\`python
# app.py
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
@app.route('/api/items', methods=['GET', 'POST'])
def handle_items():
if request.method == 'POST':
data = request.get_json()
return jsonify(data), 201
else:
return jsonify([{"name": "item1"}, {"name": "item2"}])
if __name__ == '__main__':
app.run(debug=True)
\`\`\`
## Running the Application
\`\`\`bash
python app.py
\`\`\`
## Application Factory Pattern
For larger applications, use the application factory pattern:
\`\`\`python
# app/__init__.py
from flask import Flask
def create_app():
app = Flask(__name__)
app.config.from_object('config.Config')
from app.main import bp as main_bp
app.register_blueprint(main_bp)
return app
\`\`\`
## Flask Extensions
Popular Flask extensions:
- **Flask-SQLAlchemy**: Database ORM
- **Flask-Login**: User session management
- **Flask-WTF**: Form handling and validation
- **Flask-Migrate**: Database migrations
## Next Steps
- Structure larger applications with Blueprints
- Add database integration
- Implement user authentication
- Deploy with Gunicorn
`;
}
// Helper methods for container content generation
private generateContainerFileContent(
_analysis: any,
_containerTech: ContainerTechnology,
): string {
const language = _analysis.metadata.primaryLanguage?.toLowerCase();
if (language === "python") {
return `FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]`;
} else if (language === "javascript" || language === "typescript") {
return `FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
USER node
CMD ["npm", "start"]`;
} else {
return `FROM ubuntu:22.04
WORKDIR /app
COPY . .
EXPOSE 8080
CMD ["./start.sh"]`;
}
}
private generateKubernetesManifest(analysis: any, type: string): string {
if (type === "deployment") {
return `apiVersion: apps/v1
kind: Deployment
metadata:
name: ${analysis.metadata.projectName}
labels:
app: ${analysis.metadata.projectName}
spec:
replicas: 3
selector:
matchLabels:
app: ${analysis.metadata.projectName}
template:
metadata:
labels:
app: ${analysis.metadata.projectName}
spec:
containers:
- name: ${analysis.metadata.projectName}
image: ${analysis.metadata.projectName}:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: "production"`;
} else if (type === "service") {
return `apiVersion: v1
kind: Service
metadata:
name: ${analysis.metadata.projectName}-service
spec:
selector:
app: ${analysis.metadata.projectName}
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: LoadBalancer`;
}
return "";
}
private generateContainerExamples(
_analysis: any,
_containerTech: ContainerTechnology,
): string[] {
return [
`# Build the container image
${_containerTech.name} build -t ${_analysis.metadata.projectName}:latest .`,
`# Run the container locally
${_containerTech.name} run -p 3000:3000 -d ${_analysis.metadata.projectName}:latest`,
`# View running containers
${_containerTech.name} ps`,
];
}
private generateOrchestrationExamples(
_analysis: any,
_orchestrationTech: OrchestrationTechnology,
): string[] {
return [
`# Deploy the application
kubectl apply -f k8s/`,
`# Check deployment status
kubectl get deployments`,
`# View application logs
kubectl logs -f deployment/${_analysis.metadata.projectName}`,
];
}
private generatePythonEnvironmentExamples(): string[] {
return [
`# Create virtual environment
python -m venv venv`,
`# Activate environment (Linux/macOS)
source venv/bin/activate`,
`# Install dependencies
pip install -r requirements.txt`,
];
}
private generatePythonFrameworkExamples(framework: any): string[] {
if (framework.name === "django") {
return [
`# Create Django project
django-admin startproject myproject`,
`# Run development server
python manage.py runserver`,
`# Create superuser
python manage.py createsuperuser`,
];
}
return [];
}
}
// Export the tool implementation
export const populateDiataxisContent: Tool = {
name: "populate_diataxis_content",
description:
"Intelligently populate Diataxis documentation with project-specific content",
inputSchema: {
type: "object",
properties: {
analysisId: {
type: "string",
description: "Repository analysis ID from analyze_repository tool",
},
docsPath: {
type: "string",
description: "Path to documentation directory",
},
populationLevel: {
type: "string",
enum: ["basic", "comprehensive", "intelligent"],
default: "comprehensive",
description: "Level of content generation detail",
},
includeProjectSpecific: {
type: "boolean",
default: true,
description: "Generate project-specific examples and code",
},
preserveExisting: {
type: "boolean",
default: true,
description: "Preserve any existing content",
},
technologyFocus: {
type: "array",
items: { type: "string" },
description: "Specific technologies to emphasize in content",
},
},
required: ["analysisId", "docsPath"],
},
};
export async function handlePopulateDiataxisContent(
args: any,
context?: any,
): Promise<PopulationResult> {
const engine = new ContentPopulationEngine();
return await engine.populateContent(args, context);
}
```