diff --git a/CHANGELOG.md b/CHANGELOG.md index dd387852..1fbaa491 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## v0.2.3 + +[compare changes](https://github.com/schoero/unwritten/compare/v0.2.2...v0.2.3) + +### Fixes + +- **renderer:html:** Section node title rendering ([236929f](https://github.com/schoero/unwritten/commit/236929f)) +- Interpreting of circular types ([073f8ba](https://github.com/schoero/unwritten/commit/073f8ba)) + +### Refactors + +- Preserve empty lines ([3e463ca](https://github.com/schoero/unwritten/commit/3e463ca)) + +### ❤️ Contributors + +- Roger Schönbächler + ## v0.2.2 [compare changes](https://github.com/schoero/unwritten/compare/v0.2.0...v0.2.2) diff --git a/package.json b/package.json index d440efef..b52bfcd0 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "0.2.2", + "version": "0.2.3", "type": "module", "name": "unwritten", "description": "unwritten is a cli tool that auto generates documentation from your JavaScript or TypeScript project by utilizing TSDoc or JSDoc comments.", diff --git a/src/interpreter/ast/types/array.ts b/src/interpreter/ast/types/array.ts index f3f3b798..0195ca0a 100644 --- a/src/interpreter/ast/types/array.ts +++ b/src/interpreter/ast/types/array.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/array-type */ import { TypeKind } from "unwritten:interpreter/enums/type"; +import { withLockedType } from "unwritten:interpreter/utils/ts.js"; import { getIdByTypeNode, getTypeId } from "unwritten:interpreter:ast/shared/id"; import { getPositionByNode, getPositionByType } from "unwritten:interpreter:ast/shared/position"; @@ -11,7 +12,7 @@ import type { ArrayType } from "unwritten:interpreter:type-definitions/types"; import type { InterpreterContext } from "unwritten:type-definitions/context"; -export function createArrayType(ctx: InterpreterContext, typeReference: TypeReference): ArrayType { +export const createArrayType = (ctx: InterpreterContext, typeReference: TypeReference): ArrayType => withLockedType(ctx, typeReference, () => { const typeId = getTypeId(ctx, typeReference); const position = getPositionByType(ctx, typeReference); @@ -25,7 +26,7 @@ export function createArrayType(ctx: InterpreterContext, typeReference: TypeRefe typeId }; -} +}); export function createArrayTypeByArrayTypeNode(ctx: InterpreterContext, arrayTypeNode: ArrayTypeNode): ArrayType { diff --git a/src/interpreter/ast/types/conditional.ts b/src/interpreter/ast/types/conditional.ts index aa86ea67..1b8bf9d9 100644 --- a/src/interpreter/ast/types/conditional.ts +++ b/src/interpreter/ast/types/conditional.ts @@ -1,4 +1,5 @@ import { TypeKind } from "unwritten:interpreter/enums/type"; +import { withLockedType } from "unwritten:interpreter/utils/ts.js"; import { getIdByTypeNode, getTypeId } from "unwritten:interpreter:ast/shared/id"; import { getTypeByTypeNode } from "../type"; @@ -30,7 +31,7 @@ export function createConditionalTypeByTypeNode(ctx: InterpreterContext, typeNod } -export function createConditionalType(ctx: InterpreterContext, type: TSConditionalType): ConditionalType { +export const createConditionalType = (ctx: InterpreterContext, type: TSConditionalType): ConditionalType => withLockedType(ctx, type, () => { const root = type.root; const typeId = getTypeId(ctx, type); @@ -50,4 +51,4 @@ export function createConditionalType(ctx: InterpreterContext, type: TSCondition typeId }; -} +}); diff --git a/src/interpreter/ast/types/function.ts b/src/interpreter/ast/types/function.ts index 710b6daf..08fcec17 100644 --- a/src/interpreter/ast/types/function.ts +++ b/src/interpreter/ast/types/function.ts @@ -1,5 +1,6 @@ import { EntityKind } from "unwritten:interpreter/enums/entity.js"; import { TypeKind } from "unwritten:interpreter/enums/type"; +import { withLockedType } from "unwritten:interpreter/utils/ts.js"; import { createSignatureEntity } from "unwritten:interpreter:ast/entities/index"; import { getTypeId } from "unwritten:interpreter:ast/shared/id"; @@ -9,7 +10,7 @@ import type { FunctionType } from "unwritten:interpreter:type-definitions/types" import type { InterpreterContext } from "unwritten:type-definitions/context"; -export function createFunctionType(ctx: InterpreterContext, type: ObjectType): FunctionType { +export const createFunctionType = (ctx: InterpreterContext, type: ObjectType): FunctionType => withLockedType(ctx, type, () => { const callSignatures = type.getCallSignatures(); // Types with constructSignatures are considered object types const signatures = callSignatures.map(signature => createSignatureEntity(ctx, signature, EntityKind.FunctionSignature)); @@ -23,4 +24,4 @@ export function createFunctionType(ctx: InterpreterContext, type: ObjectType): F typeId }; -} +}); diff --git a/src/interpreter/ast/types/intersection.ts b/src/interpreter/ast/types/intersection.ts index c8c6e273..c5f6f808 100644 --- a/src/interpreter/ast/types/intersection.ts +++ b/src/interpreter/ast/types/intersection.ts @@ -1,4 +1,5 @@ import { TypeKind } from "unwritten:interpreter/enums/type"; +import { withLockedType } from "unwritten:interpreter/utils/ts.js"; import { getTypeId } from "unwritten:interpreter:ast/shared/id"; import { getTypeByType } from "../type"; @@ -9,7 +10,7 @@ import type { IntersectionType } from "unwritten:interpreter:type-definitions/ty import type { InterpreterContext } from "unwritten:type-definitions/context"; -export function createIntersectionType(ctx: InterpreterContext, type: TSIntersectionType): IntersectionType { +export const createIntersectionType = (ctx: InterpreterContext, type: TSIntersectionType): IntersectionType => withLockedType(ctx, type, () => { const typeId = getTypeId(ctx, type); const types = type.types.map(type => getTypeByType(ctx, type)); @@ -21,4 +22,4 @@ export function createIntersectionType(ctx: InterpreterContext, type: TSIntersec types }; -} +}); diff --git a/src/interpreter/ast/types/union.ts b/src/interpreter/ast/types/union.ts index 68ec4631..cbce49b3 100644 --- a/src/interpreter/ast/types/union.ts +++ b/src/interpreter/ast/types/union.ts @@ -1,4 +1,5 @@ import { TypeKind } from "unwritten:interpreter/enums/type"; +import { withLockedType } from "unwritten:interpreter/utils/ts.js"; import { getTypeId } from "unwritten:interpreter:ast/shared/id"; import { getTypeByType, getTypeByTypeNode } from "../type"; @@ -9,7 +10,7 @@ import type { UnionType } from "unwritten:interpreter:type-definitions/types"; import type { InterpreterContext } from "unwritten:type-definitions/context"; -export function createUnionType(ctx: InterpreterContext, type: TSUnionType): UnionType { +export const createUnionType = (ctx: InterpreterContext, type: TSUnionType): UnionType => withLockedType(ctx, type, () => { const typeId = getTypeId(ctx, type); const types = type.types.map(type => getTypeByType(ctx, type)); @@ -21,7 +22,7 @@ export function createUnionType(ctx: InterpreterContext, type: TSUnionType): Uni types }; -} +}); export function createUnionTypeByTypeNode(ctx: InterpreterContext, typeNode: UnionTypeNode): UnionType { diff --git a/src/renderer/markup/html/ast/section.ts b/src/renderer/markup/html/ast/section.ts index d87d1fc5..82e2876a 100644 --- a/src/renderer/markup/html/ast/section.ts +++ b/src/renderer/markup/html/ast/section.ts @@ -17,16 +17,20 @@ export function renderSectionNode(ctx: HTMLRenderContext, sectionNode: SectionNo const renderedIndentation = renderIndentation(ctx); const renderedNewLine = renderNewLine(ctx); const renderedOpeningTag = `<${tag}${classAttribute}>`; + const renderedTitle = withIndentation(ctx, ctx => renderNode(ctx, sectionNode.title)); const renderedChildren = withIndentation(ctx, ctx => renderNode(ctx, sectionNode.children)); const renderedClosingTag = ``; - return renderedChildren === "" + return renderedChildren === "" && renderedTitle === "" ? "" : [ `${renderedIndentation}${renderedOpeningTag}`, + renderedTitle, renderedChildren, `${renderedIndentation}${renderedClosingTag}` - ].join(renderedNewLine); + ] + .filter(renderedNode => !!renderedNode) + .join(renderedNewLine); } function getTag(ctx: HTMLRenderContext, type?: SectionType) { diff --git a/src/renderer/markup/markdown/ast/list.test.ts b/src/renderer/markup/markdown/ast/list.test.ts index 6e89e5c3..62b184a7 100644 --- a/src/renderer/markup/markdown/ast/list.test.ts +++ b/src/renderer/markup/markdown/ast/list.test.ts @@ -197,18 +197,22 @@ scope("MarkdownRenderer", "ListNode", () => { }); - it("should collapse multiple newlines to a single new line", () => { + it("should collapse multiple empty lines to a single empty line", () => { const simpleListNode = createListNode([ - "Line 1\nLine 2\n\nLine 3\n\n\nLine 4" + "Line 1\nLine 2\n\nLine 3\n\n\nLine 4\n\n\n\nLine 5" ]); expect(renderListNode(ctx, simpleListNode)).toBe(md` - Line 1 Line 2 + Line 3 + Line 4 + Line 5 + `); }); diff --git a/src/renderer/markup/markdown/index.ts b/src/renderer/markup/markdown/index.ts index 750f5b6b..54dd29aa 100644 --- a/src/renderer/markup/markdown/index.ts +++ b/src/renderer/markup/markdown/index.ts @@ -242,7 +242,9 @@ function renderString(ctx: MarkdownRenderContext, node: string): string { // Indent all lines except the first one const indentedLines = escapedLines - .filter(node => !!node) + .filter((node, index, arr) => + // Filter multiple empty lines + !(node === "" && arr[index - 1] === "")) .map((line, index) => index === 0 ? line diff --git a/src/renderer/markup/markdown/utils/escape.test.ts b/src/renderer/markup/markdown/utils/escape.test.ts index 0fbdced7..7366f607 100644 --- a/src/renderer/markup/markdown/utils/escape.test.ts +++ b/src/renderer/markup/markdown/utils/escape.test.ts @@ -106,5 +106,34 @@ scope("Renderer", "Render abstraction", () => { `); }); + it("should preserve empty lines", () => { + const testString = md` + should preserve empty lines + + before code fences + + \`\`\`ts + inside code fences + + inside code fences + \`\`\` + + and after code fences + `; + expect(escapeMarkdown(testString)).toBe(md` + should preserve empty lines + + before code fences + + \`\`\`ts + inside code fences + + inside code fences + \`\`\` + + and after code fences + `); + }); + }); });