From e73b84651ec32ca403ba786f65c0336b3147e650 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Roger=20Sch=C3=B6nb=C3=A4chler?=
 <42278642+schoero@users.noreply.github.com>
Date: Tue, 27 Aug 2024 21:47:15 +0200
Subject: [PATCH] feat: add option to exclude internal entities

---
 .../markup/ast-converter/entities/class.ts    | 71 +++++++++++----
 .../ast-converter/entities/function-like.ts   |  6 +-
 .../ast-converter/entities/interface.ts       | 38 ++++----
 .../ast-converter/entities/signature.test.ts  |  6 +-
 src/renderer/markup/ast-converter/index.ts    |  8 +-
 .../markup/ast-converter/types/object.ts      | 21 +++--
 src/renderer/markup/config/config.test.ts     | 87 +++++++++++++++++++
 src/renderer/markup/config/default.ts         |  1 +
 .../markup/types-definitions/config.ts        |  3 +
 src/renderer/markup/utils/filter.ts           | 84 ++++++++++++++++++
 src/renderer/markup/utils/sort.ts             |  5 +-
 src/renderer/utils/private-members.ts         | 26 ------
 12 files changed, 277 insertions(+), 79 deletions(-)
 create mode 100644 src/renderer/markup/utils/filter.ts
 delete mode 100644 src/renderer/utils/private-members.ts

diff --git a/src/renderer/markup/ast-converter/entities/class.ts b/src/renderer/markup/ast-converter/entities/class.ts
index e944693b..cc3105de 100644
--- a/src/renderer/markup/ast-converter/entities/class.ts
+++ b/src/renderer/markup/ast-converter/entities/class.ts
@@ -1,9 +1,13 @@
 import { convertSeeTagsForDocumentation } from "unwritten:renderer/markup/ast-converter/shared/see";
 import { registerAnchor, registerAnonymousAnchor } from "unwritten:renderer/markup/registry/registry";
 import { renderMemberContext, withMemberContext } from "unwritten:renderer/markup/utils/context";
+import {
+  implicitSignatureFilter,
+  internalMemberFilter,
+  privateMemberFilter
+} from "unwritten:renderer/markup/utils/filter";
 import { isRenderObjectMemberTitlesEnabled, renderEntityPrefix } from "unwritten:renderer/markup/utils/renderer.js";
 import { getRenderConfig } from "unwritten:renderer/utils/config";
-import { filterOutImplicitSignatures, filterOutPrivateMembers } from "unwritten:renderer/utils/private-members";
 import {
   convertEventPropertyEntityForDocumentation,
   convertEventPropertyEntityForTableOfContents,
@@ -86,14 +90,33 @@ export function convertClassEntityForTableOfContents(ctx: MarkupRenderContext, c
     const getterEntities = extendClassEntityEntitiesWithHeritage(classEntity, "getters");
     const eventPropertyEntities = extendClassEntityEntitiesWithHeritage(classEntity, "events");
 
-    const publicConstructorEntity = renderConfig.renderPrivateMembers ? constructorEntity : constructorEntity && filterOutPrivateMembers([constructorEntity])[0];
-    const publicPropertyEntities = renderConfig.renderPrivateMembers ? propertyEntities : filterOutPrivateMembers(propertyEntities);
-    const publicMethodEntities = renderConfig.renderPrivateMembers ? methodEntities : filterOutPrivateMembers(methodEntities);
-    const publicSetterEntities = renderConfig.renderPrivateMembers ? setterEntities : filterOutPrivateMembers(setterEntities);
-    const publicGetterEntities = renderConfig.renderPrivateMembers ? getterEntities : filterOutPrivateMembers(getterEntities);
-    const publicEventPropertyEntities = renderConfig.renderPrivateMembers ? eventPropertyEntities : filterOutPrivateMembers(eventPropertyEntities);
+    const publicConstructorEntity = [constructorEntity]
+      .filter(privateMemberFilter, ctx)
+      .filter(internalMemberFilter, ctx)[0];
+
+    const publicPropertyEntities = propertyEntities
+      .filter(privateMemberFilter, ctx)
+      .filter(internalMemberFilter, ctx);
+
+    const publicMethodEntities = methodEntities
+      .filter(privateMemberFilter, ctx)
+      .filter(internalMemberFilter, ctx);
+
+    const publicSetterEntities = setterEntities
+      .filter(privateMemberFilter, ctx)
+      .filter(internalMemberFilter, ctx);
+
+    const publicGetterEntities = getterEntities
+      .filter(privateMemberFilter, ctx)
+      .filter(internalMemberFilter, ctx);
+
+    const publicEventPropertyEntities = eventPropertyEntities
+      .filter(privateMemberFilter, ctx)
+      .filter(internalMemberFilter, ctx);
+
+    const explicitConstructSignatures = publicConstructorEntity?.signatures
+      ?.filter(implicitSignatureFilter);
 
-    const explicitConstructSignatures = publicConstructorEntity?.signatures && filterOutImplicitSignatures(publicConstructorEntity.signatures);
     const convertedConstructSignatures = explicitConstructSignatures?.map(signatureEntity => convertSignatureEntityForTableOfContents(ctx, signatureEntity));
     const convertedProperties = publicPropertyEntities.map(propertyEntity => convertPropertyEntityForTableOfContents(ctx, propertyEntity));
     const convertedMethods = publicMethodEntities.flatMap(methodEntity => convertFunctionLikeEntityForTableOfContents(ctx, methodEntity)).flat();
@@ -189,14 +212,32 @@ export function convertClassEntityForDocumentation(ctx: MarkupRenderContext, cla
     const getterEntities = extendClassEntityEntitiesWithHeritage(classEntity, "getters");
     const eventPropertyEntities = extendClassEntityEntitiesWithHeritage(classEntity, "events");
 
-    const publicConstructorEntity = renderConfig.renderPrivateMembers ? constructorEntity : constructorEntity && filterOutPrivateMembers([constructorEntity])[0];
-    const publicPropertyEntities = renderConfig.renderPrivateMembers ? propertyEntities : filterOutPrivateMembers(propertyEntities);
-    const publicMethodEntities = renderConfig.renderPrivateMembers ? methodEntities : filterOutPrivateMembers(methodEntities);
-    const publicSetterEntities = renderConfig.renderPrivateMembers ? setterEntities : filterOutPrivateMembers(setterEntities);
-    const publicGetterEntities = renderConfig.renderPrivateMembers ? getterEntities : filterOutPrivateMembers(getterEntities);
-    const publicEventPropertyEntities = renderConfig.renderPrivateMembers ? eventPropertyEntities : filterOutPrivateMembers(eventPropertyEntities);
+    const publicConstructorEntity = [constructorEntity]
+      .filter(privateMemberFilter, ctx)
+      .filter(internalMemberFilter, ctx)[0];
+
+    const publicPropertyEntities = propertyEntities
+      .filter(privateMemberFilter, ctx)
+      .filter(internalMemberFilter, ctx);
+
+    const publicMethodEntities = methodEntities
+      .filter(privateMemberFilter, ctx)
+      .filter(internalMemberFilter, ctx);
+
+    const publicSetterEntities = setterEntities
+      .filter(privateMemberFilter, ctx)
+      .filter(internalMemberFilter, ctx);
+
+    const publicGetterEntities = getterEntities
+      .filter(privateMemberFilter, ctx)
+      .filter(internalMemberFilter, ctx);
+
+    const publicEventPropertyEntities = eventPropertyEntities
+      .filter(privateMemberFilter, ctx)
+      .filter(internalMemberFilter, ctx);
 
-    const explicitConstructSignatures = publicConstructorEntity?.signatures && filterOutImplicitSignatures(publicConstructorEntity.signatures);
+    const explicitConstructSignatures = publicConstructorEntity?.signatures
+      ?.filter(implicitSignatureFilter);
 
     const hasConstructSignatures = explicitConstructSignatures && explicitConstructSignatures.length > 0;
     const constructSignaturesTranslation = translate("constructSignature", { capitalizeEach: true, count: explicitConstructSignatures?.length });
diff --git a/src/renderer/markup/ast-converter/entities/function-like.ts b/src/renderer/markup/ast-converter/entities/function-like.ts
index fde164ef..8ae4f230 100644
--- a/src/renderer/markup/ast-converter/entities/function-like.ts
+++ b/src/renderer/markup/ast-converter/entities/function-like.ts
@@ -1,4 +1,4 @@
-import { filterOutImplicitSignatures } from "unwritten:renderer/utils/private-members";
+import { implicitSignatureFilter } from "unwritten:renderer/markup/utils/filter";
 import {
   convertSignatureEntityForDocumentation,
   convertSignatureEntityForTableOfContents,
@@ -15,14 +15,14 @@ import type {
 
 
 export function convertFunctionLikeEntityForTableOfContents(ctx: MarkupRenderContext, functionLikeEntity: FunctionLikeEntity): ConvertedFunctionEntityForTableOfContents {
-  const explicitSignatures = filterOutImplicitSignatures(functionLikeEntity.signatures);
+  const explicitSignatures = functionLikeEntity.signatures.filter(implicitSignatureFilter);
   return explicitSignatures.map(
     signature => convertSignatureEntityForTableOfContents(ctx, signature)
   );
 }
 
 export function convertFunctionLikeEntityForDocumentation(ctx: MarkupRenderContext, functionLikeEntity: FunctionLikeEntity): ConvertedFunctionEntityForDocumentation {
-  const explicitSignatures = filterOutImplicitSignatures(functionLikeEntity.signatures);
+  const explicitSignatures = functionLikeEntity.signatures.filter(implicitSignatureFilter);
   return explicitSignatures.map(
     signature => convertSignatureEntityForDocumentation(ctx, signature)
   );
diff --git a/src/renderer/markup/ast-converter/entities/interface.ts b/src/renderer/markup/ast-converter/entities/interface.ts
index 6473a820..c4b51884 100644
--- a/src/renderer/markup/ast-converter/entities/interface.ts
+++ b/src/renderer/markup/ast-converter/entities/interface.ts
@@ -1,13 +1,15 @@
 import { convertSeeTagsForDocumentation } from "unwritten:renderer/markup/ast-converter/shared/see";
 import { registerAnchor } from "unwritten:renderer/markup/registry/registry";
 import { renderMemberContext } from "unwritten:renderer/markup/utils/context";
+import {
+  implicitSignatureFilter,
+  internalMemberFilter,
+  internalSignatureFilter,
+  privateMemberFilter,
+  privateSignatureFilter
+} from "unwritten:renderer/markup/utils/filter";
 import { renderEntityPrefix } from "unwritten:renderer/markup/utils/renderer.js";
 import { getRenderConfig } from "unwritten:renderer/utils/config";
-import {
-  filterOutImplicitSignatures,
-  filterOutPrivateMembers,
-  filterOutPrivateSignatures
-} from "unwritten:renderer/utils/private-members";
 import {
   convertEventPropertyEntityForType,
   convertPropertyEntityForType,
@@ -106,19 +108,19 @@ export function convertInterfaceEntityForDocumentation(ctx: MarkupRenderContext,
   const setterSignatures = extendInterfaceEntitySignaturesWithHeritage(interfaceEntity, "setterSignatures");
   const getterSignatures = extendInterfaceEntitySignaturesWithHeritage(interfaceEntity, "getterSignatures");
 
-  const publicPropertyEntities = renderConfig.renderPrivateMembers ? propertyEntities : filterOutPrivateMembers(propertyEntities);
-  const publicEventPropertyEntities = renderConfig.renderPrivateMembers ? eventPropertyEntities : filterOutPrivateMembers(eventPropertyEntities);
-  const publicConstructSignatures = renderConfig.renderPrivateMembers ? constructSignatureEntities : filterOutPrivateSignatures(constructSignatureEntities);
-  const publicCallSignatures = renderConfig.renderPrivateMembers ? callSignatureEntities : filterOutPrivateSignatures(callSignatureEntities);
-  const publicMethodSignatures = renderConfig.renderPrivateMembers ? methodSignatures : filterOutPrivateSignatures(methodSignatures);
-  const publicSetterSignatures = renderConfig.renderPrivateMembers ? setterSignatures : filterOutPrivateSignatures(setterSignatures);
-  const publicGetterSignatures = renderConfig.renderPrivateMembers ? getterSignatures : filterOutPrivateSignatures(getterSignatures);
-
-  const explicitConstructSignatures = filterOutImplicitSignatures(publicConstructSignatures);
-  const explicitCallSignatures = filterOutImplicitSignatures(publicCallSignatures);
-  const explicitMethodSignatures = filterOutImplicitSignatures(publicMethodSignatures);
-  const explicitSetterSignatures = filterOutImplicitSignatures(publicSetterSignatures);
-  const explicitGetterSignatures = filterOutImplicitSignatures(publicGetterSignatures);
+  const publicPropertyEntities = propertyEntities.filter(privateMemberFilter, ctx).filter(internalMemberFilter, ctx);
+  const publicEventPropertyEntities = eventPropertyEntities.filter(privateMemberFilter, ctx).filter(internalMemberFilter, ctx);
+  const publicConstructSignatures = constructSignatureEntities.filter(privateSignatureFilter, ctx).filter(internalSignatureFilter, ctx);
+  const publicCallSignatures = callSignatureEntities.filter(privateSignatureFilter, ctx).filter(internalSignatureFilter, ctx);
+  const publicMethodSignatures = methodSignatures.filter(privateSignatureFilter, ctx).filter(internalSignatureFilter, ctx);
+  const publicSetterSignatures = setterSignatures.filter(privateSignatureFilter, ctx).filter(internalSignatureFilter, ctx);
+  const publicGetterSignatures = getterSignatures.filter(privateSignatureFilter, ctx).filter(internalSignatureFilter, ctx);
+
+  const explicitConstructSignatures = publicConstructSignatures.filter(implicitSignatureFilter);
+  const explicitCallSignatures = publicCallSignatures.filter(implicitSignatureFilter);
+  const explicitMethodSignatures = publicMethodSignatures.filter(implicitSignatureFilter);
+  const explicitSetterSignatures = publicSetterSignatures.filter(implicitSignatureFilter);
+  const explicitGetterSignatures = publicGetterSignatures.filter(implicitSignatureFilter);
 
   const properties = publicPropertyEntities.map(propertyEntity => convertPropertyEntityForType(ctx, propertyEntity));
   const eventProperties = publicEventPropertyEntities.map(eventPropertyEntity => convertEventPropertyEntityForType(ctx, eventPropertyEntity));
diff --git a/src/renderer/markup/ast-converter/entities/signature.test.ts b/src/renderer/markup/ast-converter/entities/signature.test.ts
index 930c6b71..7d839b79 100644
--- a/src/renderer/markup/ast-converter/entities/signature.test.ts
+++ b/src/renderer/markup/ast-converter/entities/signature.test.ts
@@ -1,7 +1,7 @@
 import { assert, expect, it } from "vitest";
 
 import { createFunctionEntity, createVariableEntity } from "unwritten:interpreter/ast/entities/index";
-import { filterOutImplicitSignatures } from "unwritten:renderer/utils/private-members";
+import { implicitSignatureFilter } from "unwritten:renderer/markup/utils/filter";
 import {
   convertSignatureEntityForDocumentation,
   convertSignatureEntityForTableOfContents
@@ -46,7 +46,7 @@ scope("MarkupRenderer", "Signature", () => {
 
     const symbol = exportedSymbols.find(s => s.name === "testSignature")!;
     const functionEntity = createFunctionEntity(compilerContext, symbol);
-    const signatureEntity = filterOutImplicitSignatures(functionEntity.signatures)[0];
+    const signatureEntity = functionEntity.signatures.filter(implicitSignatureFilter)[0];
     const ctx = createRenderContext();
 
     const convertedSignatureForTableOfContents = convertSignatureEntityForTableOfContents(ctx, signatureEntity);
@@ -156,7 +156,7 @@ scope("MarkupRenderer", "Signature", () => {
 
     const symbol = exportedSymbols.find(s => s.name === "testSignature")!;
     const functionEntity = createFunctionEntity(compilerContext, symbol);
-    const signatureEntity = filterOutImplicitSignatures(functionEntity.signatures)[0];
+    const signatureEntity = functionEntity.signatures.filter(implicitSignatureFilter)[0];
     const ctx = createRenderContext();
 
     const convertedSignatureForTableOfContents = convertSignatureEntityForTableOfContents(ctx, signatureEntity);
diff --git a/src/renderer/markup/ast-converter/index.ts b/src/renderer/markup/ast-converter/index.ts
index b5f6a361..8438347f 100644
--- a/src/renderer/markup/ast-converter/index.ts
+++ b/src/renderer/markup/ast-converter/index.ts
@@ -1,5 +1,7 @@
 import { registerAnonymousAnchor } from "unwritten:renderer/markup/registry/registry";
 import { getSectionType, pluralizeEntityKind } from "unwritten:renderer/markup/types-definitions/sections.js";
+import { filterExportableEntities } from "unwritten:renderer/markup/utils/filter";
+import { sortExportableEntities } from "unwritten:renderer/markup/utils/sort";
 import {
   convertCircularEntityToAnchor,
   convertClassEntityForDocumentation,
@@ -35,7 +37,6 @@ import {
 } from "unwritten:renderer:markup/ast-converter/entities/index";
 import { createListNode, createSectionNode, createTitleNode } from "unwritten:renderer:markup/utils/nodes";
 import { renderCategoryName } from "unwritten:renderer:markup/utils/renderer";
-import { sortExportableEntities } from "unwritten:renderer:markup/utils/sort";
 import {
   isCircularEntity,
   isClassEntity,
@@ -156,9 +157,10 @@ export function convertEntityForDocumentation(ctx: MarkupRenderContext, entity:
 export function convertToMarkupAST(ctx: MarkupRenderContext, entities: ExportableEntity[]) {
 
   const sortedEntities = sortExportableEntities(ctx, entities);
+  const filteredEntities = filterExportableEntities(ctx, sortedEntities);
 
-  const tableOfContents = createTableOfContents(ctx, sortedEntities);
-  const documentation = createDocumentation(ctx, sortedEntities);
+  const tableOfContents = createTableOfContents(ctx, filteredEntities);
+  const documentation = createDocumentation(ctx, filteredEntities);
 
   return {
     documentation,
diff --git a/src/renderer/markup/ast-converter/types/object.ts b/src/renderer/markup/ast-converter/types/object.ts
index e798beaf..e8616024 100644
--- a/src/renderer/markup/ast-converter/types/object.ts
+++ b/src/renderer/markup/ast-converter/types/object.ts
@@ -1,6 +1,11 @@
 import { TypeKind } from "unwritten:interpreter/enums/type";
+import {
+  internalMemberFilter,
+  internalSignatureFilter,
+  privateMemberFilter,
+  privateSignatureFilter
+} from "unwritten:renderer/markup/utils/filter";
 import { getRenderConfig } from "unwritten:renderer/utils/config";
-import { filterOutPrivateMembers, filterOutPrivateSignatures } from "unwritten:renderer/utils/private-members";
 import {
   convertEventPropertyEntityForType,
   convertFunctionLikeEntityForType,
@@ -46,13 +51,13 @@ export function convertObjectTypeMultiline(
 
   const renderConfig = getRenderConfig(ctx);
 
-  const constructSignatures = renderConfig.renderPrivateMembers ? objectLikeType.constructSignatures : filterOutPrivateSignatures(objectLikeType.constructSignatures);
-  const callSignatures = renderConfig.renderPrivateMembers ? objectLikeType.callSignatures : filterOutPrivateSignatures(objectLikeType.callSignatures);
-  const properties = renderConfig.renderPrivateMembers ? objectLikeType.properties : filterOutPrivateMembers(objectLikeType.properties);
-  const methods = renderConfig.renderPrivateMembers ? objectLikeType.methods : filterOutPrivateMembers(objectLikeType.methods);
-  const setters = renderConfig.renderPrivateMembers ? objectLikeType.setters : filterOutPrivateMembers(objectLikeType.setters);
-  const getters = renderConfig.renderPrivateMembers ? objectLikeType.getters : filterOutPrivateMembers(objectLikeType.getters);
-  const events = renderConfig.renderPrivateMembers ? objectLikeType.events : filterOutPrivateMembers(objectLikeType.events);
+  const constructSignatures = objectLikeType.constructSignatures.filter(privateSignatureFilter, ctx).filter(internalSignatureFilter, ctx);
+  const callSignatures = objectLikeType.callSignatures.filter(privateSignatureFilter, ctx).filter(internalSignatureFilter, ctx);
+  const properties = objectLikeType.properties.filter(privateMemberFilter, ctx).filter(internalMemberFilter, ctx);
+  const methods = objectLikeType.methods.filter(privateMemberFilter, ctx).filter(internalMemberFilter, ctx);
+  const setters = objectLikeType.setters.filter(privateMemberFilter, ctx).filter(internalMemberFilter, ctx);
+  const getters = objectLikeType.getters.filter(privateMemberFilter, ctx).filter(internalMemberFilter, ctx);
+  const events = objectLikeType.events.filter(privateMemberFilter, ctx).filter(internalMemberFilter, ctx);
 
   const convertedConstructSignatures = constructSignatures.map(
     constructSignature => {
diff --git a/src/renderer/markup/config/config.test.ts b/src/renderer/markup/config/config.test.ts
index 784ebc47..5f67f7e5 100644
--- a/src/renderer/markup/config/config.test.ts
+++ b/src/renderer/markup/config/config.test.ts
@@ -205,4 +205,91 @@ scope("Renderer", "Config", () => {
 
   });
 
+  describe("renderInternalEntities", async () => {
+
+    {
+
+      const testFileContent = ts`
+        export class Class {
+          /** @internal */
+          public constructor() {}
+          /** @internal */
+          public property: number = 1;
+          /** @internal */
+          public method(): void {}
+        }
+      `;
+
+      const { ctx: compilerContext, exportedSymbols, fileSymbols } = compile(testFileContent);
+
+      const classSymbol = exportedSymbols.find(s => s.name === "Class")!;
+      const classEntity = createClassEntity(compilerContext, classSymbol);
+
+      const ctx = createRenderContext();
+
+      {
+        const convertedClassForDocumentation = convertClassEntityForDocumentation(ctx, classEntity);
+
+        const titleNode = convertedClassForDocumentation.title;
+
+        assert(isSectionNode(convertedClassForDocumentation));
+        assert(isTitleNode(titleNode));
+
+        const [
+          position,
+          tags,
+          description,
+          remarks,
+          example,
+          constructSignatures,
+          properties,
+          methods,
+          setters,
+          getters
+        ] = titleNode.children;
+
+        it("should not have any internal members when disabled", () => {
+          expect(constructSignatures).toBeFalsy();
+          expect(properties).toBeFalsy();
+          expect(methods).toBeFalsy();
+        });
+
+      }
+
+      ctx.config.renderConfig.html.renderInternalEntities = true;
+
+      {
+        const convertedClassForDocumentation = convertClassEntityForDocumentation(ctx, classEntity);
+
+        const titleNode = convertedClassForDocumentation.title;
+
+        assert(isSectionNode(convertedClassForDocumentation));
+        assert(isTitleNode(titleNode));
+
+        const [
+          position,
+          tags,
+          description,
+          remarks,
+          example,
+          see,
+          constructSignatures,
+          properties,
+          methods,
+          setters,
+          getters
+        ] = titleNode.children;
+
+        it("should have internal members when enabled", () => {
+          expect(constructSignatures && constructSignatures.children).toHaveLength(1);
+          expect(properties && properties.children.flat()).toHaveLength(1);
+          expect(methods && methods.children.flat()).toHaveLength(1);
+        });
+
+      }
+
+    }
+
+  });
+
 });
diff --git a/src/renderer/markup/config/default.ts b/src/renderer/markup/config/default.ts
index 532465f7..13992ee2 100644
--- a/src/renderer/markup/config/default.ts
+++ b/src/renderer/markup/config/default.ts
@@ -18,6 +18,7 @@ const defaultRenderConfig: Complete<MarkupRenderConfig> = {
   renderClassMemberTitles: "tableOfContents",
   renderDefaultValuesAsOptional: true,
   renderEntityPrefixes: "documentation",
+  renderInternalEntities: false,
   renderOrder: [
     EntityKind.Module,
     EntityKind.Namespace,
diff --git a/src/renderer/markup/types-definitions/config.ts b/src/renderer/markup/types-definitions/config.ts
index a2231a52..79f2f110 100644
--- a/src/renderer/markup/types-definitions/config.ts
+++ b/src/renderer/markup/types-definitions/config.ts
@@ -46,6 +46,9 @@ export interface MarkupRenderConfig {
   /** Defines whether the renderer should render private members. */
   renderPrivateMembers?: boolean;
 
+  /** Defines whether entities marked with an `@internal` tag should appear in the rendered output. */
+  renderInternalEntities?: boolean;
+
   /** Defines whether the renderer should render links to the source code. */
   renderSourceCodeLinks?: boolean;
 
diff --git a/src/renderer/markup/utils/filter.ts b/src/renderer/markup/utils/filter.ts
new file mode 100644
index 00000000..a8f11526
--- /dev/null
+++ b/src/renderer/markup/utils/filter.ts
@@ -0,0 +1,84 @@
+import { getRenderConfig } from "unwritten:renderer/utils/config";
+import { isFunctionLikeEntity } from "unwritten:typeguards/entities";
+
+import type {
+  ExplicitSignatureEntity,
+  ExportableEntity,
+  FunctionLikeEntity,
+  PropertyEntity,
+  SignatureEntity
+} from "unwritten:interpreter:type-definitions/entities";
+import type { MarkupRenderContext } from "unwritten:renderer/markup/types-definitions/markup";
+
+
+export function filterExportableEntities(ctx: MarkupRenderContext, entities: ExportableEntity[]): ExportableEntity[] {
+
+  const renderInternal = ctx.config.renderConfig[ctx.renderer.name].renderInternalEntities;
+
+  return entities.filter(entity => {
+    const isInternal = "internal" in entity && entity.internal;
+    return renderInternal || !isInternal;
+  });
+
+}
+
+
+export function implicitSignatureFilter(signature: SignatureEntity): signature is ExplicitSignatureEntity {
+  return signature.declarationId !== undefined;
+}
+
+export function internalMemberFilter<Entity extends FunctionLikeEntity | PropertyEntity>(this: MarkupRenderContext, entity: Entity | undefined): boolean {
+  if(entity === undefined){
+    return false;
+  }
+
+  const renderConfig = getRenderConfig(this);
+
+  if(renderConfig.renderInternalEntities){
+    return true;
+  }
+
+  if(isFunctionLikeEntity(entity)){
+    return entity.signatures.every(signature => !signature.internal);
+  }
+
+  return !entity.internal;
+}
+
+export function internalSignatureFilter(this: MarkupRenderContext, signature: SignatureEntity | undefined): boolean {
+  if(signature === undefined){
+    return false;
+  }
+
+  const renderConfig = getRenderConfig(this);
+
+  return renderConfig.renderInternalEntities || !signature.internal;
+}
+
+export function privateMemberFilter<Entity extends FunctionLikeEntity | PropertyEntity>(this: MarkupRenderContext, entity: Entity | undefined): boolean {
+  if(entity === undefined){
+    return false;
+  }
+
+  const renderConfig = getRenderConfig(this);
+
+  if(renderConfig.renderPrivateMembers){
+    return true;
+  }
+
+  if(isFunctionLikeEntity(entity)){
+    return entity.signatures.every(signature => !signature.modifiers?.includes("private"));
+  }
+
+  return !entity.modifiers?.includes("private");
+}
+
+export function privateSignatureFilter(this: MarkupRenderContext, signature: SignatureEntity | undefined): boolean {
+  if(signature === undefined){
+    return false;
+  }
+
+  const renderConfig = getRenderConfig(this);
+
+  return renderConfig.renderPrivateMembers || !signature.modifiers?.includes("private");
+}
diff --git a/src/renderer/markup/utils/sort.ts b/src/renderer/markup/utils/sort.ts
index a3b078e8..c2510b78 100644
--- a/src/renderer/markup/utils/sort.ts
+++ b/src/renderer/markup/utils/sort.ts
@@ -1,6 +1,5 @@
-import type { MarkupRenderContext } from "../types-definitions/markup";
-
-import type { ExportableEntity } from "unwritten:interpreter:type-definitions/entities";
+import type { ExportableEntity } from "unwritten:interpreter/type-definitions/entities";
+import type { MarkupRenderContext } from "unwritten:renderer/markup/types-definitions/markup";
 
 
 export function sortExportableEntities(ctx: MarkupRenderContext, entities: ExportableEntity[]): ExportableEntity[] {
diff --git a/src/renderer/utils/private-members.ts b/src/renderer/utils/private-members.ts
deleted file mode 100644
index a65a64d4..00000000
--- a/src/renderer/utils/private-members.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { isFunctionLikeEntity } from "unwritten:typeguards/entities";
-
-import type {
-  ExplicitSignatureEntity,
-  FunctionLikeEntity,
-  PropertyEntity,
-  SignatureEntity
-} from "unwritten:interpreter:type-definitions/entities";
-
-
-export function filterOutImplicitSignatures(signatures: SignatureEntity[]): ExplicitSignatureEntity[] {
-  return signatures.filter(signature => signature.declarationId !== undefined) as ExplicitSignatureEntity[];
-}
-
-export function filterOutPrivateMembers<Entities extends FunctionLikeEntity | PropertyEntity>(entities: Entities[]): Entities[] {
-  return entities.filter(entity => {
-    if(isFunctionLikeEntity(entity)){
-      return entity.signatures.every(signature => !signature.modifiers?.includes("private"));
-    }
-    return !entity.modifiers?.includes("private");
-  });
-}
-
-export function filterOutPrivateSignatures(signatures: SignatureEntity[]): SignatureEntity[] {
-  return signatures.filter(signature => !signature.modifiers?.includes("private"));
-}