Skip to content

Commit

Permalink
feat!: type metadata
Browse files Browse the repository at this point in the history
Signed-off-by: Lexus Drumgold <[email protected]>
  • Loading branch information
unicornware committed Jul 5, 2024
1 parent 2641b5f commit ccb141f
Show file tree
Hide file tree
Showing 162 changed files with 5,641 additions and 344 deletions.
113 changes: 53 additions & 60 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ It implements the [**unist**][unist] spec.
- [Types](#types)
- [Nodes (abstract)](#nodes-abstract)
- [`Node`](#node)
- [`Position`](#position)
- [`Point`](#point)
- [`Literal`](#literal)
- [`Parent`](#parent)
- [Nodes](#nodes)
Expand All @@ -35,7 +33,7 @@ It implements the [**unist**][unist] spec.
- [`Description`](#description)
- [`InlineTag`](#inlinetag)
- [`Root`](#root)
- [`TypeExpression`](#typeexpression)
- [`TypeMetadata`](#typemetadata)
- [Mixins](#mixins)
- [`Tag`](#tag)
- [`TagName`](#tagname)
Expand All @@ -44,6 +42,7 @@ It implements the [**unist**][unist] spec.
- [`DescriptionContent`](#descriptioncontent)
- [`FlowContent`](#flowcontent)
- [`PhrasingContent`](#phrasingcontent)
- [`TypeExpression`](#typeexpression)
- [Glossary](#glossary)
- [List of utilities](#list-of-utilities)
- [Contribute](#contribute)
Expand Down Expand Up @@ -80,62 +79,20 @@ yarn add @flex-development/docast
### `Node`

```ts
interface Node extends unist.Node {
position?: Position | undefined
}
interface Node extends unist.Node {}
```

**Node** ([**unist.Node**][unist-node]) is a syntactic unit in docast syntax trees.

The `position` field represents the location of a node in a source document. The value of the `position` field implements
the [`Position`](#position) interface. The `position` field must not be present if a node is [*generated*][unist-generated].

#### `Position`

```ts
interface Position {
end: Point
start: Point
}
```

**Position** represents the location of a node in a source [*file*][unist-file].

The `start` field of **Position** represents the index of the first character of the parsed source region. The `end`
field represents the index of the first character after the parsed source region, whether it exists or not. The value
of the `start` and `end` fields implement the [**Point**](#point) interface.

If the syntactic unit represented by a node is not present in the source [*file*][unist-file] at the time of parsing,
the node is said to be [*generated*][unist-generated] and it must not have positional information.

#### `Point`

```ts
interface Point {
column: number // >= 1
line: number // >= 1
offset: number // >= 0
}
```

**Point** represents one place in a source [*file*][unist-file].

The `line` and `column` fields are `1`-indexed integers representing a line and column in a source file. The offset
field (`0`-indexed integer) represents a character in a source file.

The term character refers to a (UTF-16) code unit as defined by the [Web IDL specification][webidl-spec].

### `Literal`

```ts
interface Literal extends Node {
value: string
value: bigint | boolean | number | string | null | undefined
}
```

**Literal** represents an abstract interface in docast containing a value.

Its `value` field is a `string`.
**Literal** represents an abstract interface in docast containing the smallest possible value.

### `Parent`

Expand All @@ -157,8 +114,8 @@ Its content is limited to [docast content](#content-model) and [mdast content][m
```ts
interface BlockTag extends Parent, Tag {
children:
| Exclude<BlockTagContent, TypeExpression>[]
| [TypeExpression, ...Exclude<BlockTagContent, TypeExpression>[]]
| Exclude<BlockTagContent, TypeMetadata>[]
| [TypeMetadata, ...Exclude<BlockTagContent, TypeMetadata>[]]
data?: BlockTagData | undefined
type: 'blockTag'
}
Expand Down Expand Up @@ -228,6 +185,7 @@ a comment, before any [**block tags**](#blocktag), and may contain [Markdown][md
interface InlineTag extends Literal, Tag {
data?: InlineTagData | undefined
type: 'inlineTag'
value: string
}
```

Expand All @@ -254,19 +212,18 @@ interface Root extends Parent {
**Root** can be used as the [*root*][unist-root] of a [*tree*][unist-tree], never as a [*child*][unist-child]. It can
contain [**comment**](#comment) nodes.

### `TypeExpression`
### `TypeMetadata`

```ts
interface TypeExpression extends Literal {
data?: TypeExpressionData | undefined
type: 'typeExpression'
interface TypeMetadata extends Literal {
data?: TypeMetadataData | undefined
type: 'typeMetadata'
}
```

**TypeExpression** ([**Literal**](#literal)) represents a type defintion or constraint.
**TypeMetadata** ([**Literal**](#literal)) represents an inlined type expression.

**TypeExpression** can be used in [**block tag**](#blocktag) nodes. It cannot contain any children &mdash; it is a
[*leaf*][unist-leaf].
**TypeMetadata** can be used in [**block tag**](#blocktag) nodes. Its content model is [**type expresssion**](#typeexpression).

## Mixins

Expand Down Expand Up @@ -301,7 +258,7 @@ falls into one or more categories of `Content`.
### `BlockTagContent`
```ts
type BlockTagContent = PhrasingContent | TypeExpression
type BlockTagContent = PhrasingContent | TypeMetadata
```
**Block** content represents [**block tag**](#blocktag) text, and its markup.
Expand Down Expand Up @@ -339,6 +296,44 @@ type PhrasingContent = InlineTag | mdast.Code | mdast.PhrasingContent
**Phrasing** content represents [**comment**](#comment) text, and its markup.
### `TypeExpression`
```ts
type TypeExpression =
| ArrayType
| AssertionPredicate
| BigIntLiteral
| BooleanLiteral
| ConditionalType
| ConstructorType
| FunctionType
| GenericType
| Identifier
| InferType
| IntersectionType
| NonNullableType
| NullLiteral
| NullableType
| NumberLiteral
| ObjectLiteralType
| OptionalType
| ParenthesizedType
| PropertyAccessType
| StringLiteral
| Super
| TemplateLiteral
| This
| TupleType
| TypeOperation
| TypePredicate
| TypeSymbol
| UndefinedLiteral
| UnionType
| VariadicType
```
**TODO**: update documentation
## Glossary
See the [unist glossary][unist-glossary] for more terms.
Expand Down Expand Up @@ -382,7 +377,6 @@ community you agree to abide by its terms.
[typescript]: https://typescriptlang.org
[unist-child]: https://github.com/syntax-tree/unist#child
[unist-file]: https://github.com/syntax-tree/unist#file
[unist-generated]: https://github.com/syntax-tree/unist#generated
[unist-glossary]: https://github.com/syntax-tree/unist#glossary
[unist-leaf]: https://github.com/syntax-tree/unist#leaf
[unist-node]: https://github.com/syntax-tree/unist#node
Expand All @@ -392,5 +386,4 @@ community you agree to abide by its terms.
[unist-tree]: https://github.com/syntax-tree/unist#tree
[unist-utilities]: https://github.com/syntax-tree/unist#list-of-utilities
[unist]: https://github.com/syntax-tree/unist
[webidl-spec]: https://webidl.spec.whatwg.org/
[wiki-comment]: https://en.wikipedia.org/wiki/Comment_(computer_programming)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
"typecheck:watch": "vitest --mode=typecheck --typecheck"
},
"dependencies": {
"@flex-development/tutils": "6.0.0-alpha.25",
"@flex-development/unist-util-types": "1.6.1",
"@types/mdast": "4.0.4",
"@types/unist": "3.0.2"
Expand All @@ -84,6 +83,7 @@
"@flex-development/mlly": "1.0.0-alpha.18",
"@flex-development/pathe": "2.0.0",
"@flex-development/tsconfig-utils": "2.0.2",
"@flex-development/tutils": "6.0.0-alpha.25",
"@stylistic/eslint-plugin": "2.3.0",
"@types/eslint": "8.56.10",
"@types/eslint__js": "8.42.3",
Expand Down
32 changes: 32 additions & 0 deletions src/__tests__/docast.spec-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* @file Type Tests - docast
* @module docast/nodes/tests/unit-d/docast
*/

import type * as TestSubject from '@flex-development/docast'
import type { Children } from '@flex-development/unist-util-types'
import type { Node } from 'unist'

describe('unit-d:docast', () => {
describe('DocastNode', () => {
type Subject = TestSubject.DocastNode

it('should be union of nodes', () => {
expectTypeOf<Extract<Subject, Node>>().toEqualTypeOf<Subject>()
})
})

describe('Extract<AnyParent, DocastNode>', () => {
type Subject = Extract<TestSubject.AnyParent, TestSubject.DocastNode>

it('should override Parent["children"]', () => {
// Arrange
type Helper<T extends unknown[]> = T extends Children<TestSubject.Parent>
? Children<TestSubject.Parent> extends T ? 0 : 1
: unknown

// Expect
expectTypeOf<Helper<Children<Subject>>>().toEqualTypeOf<1>()
})
})
})
6 changes: 3 additions & 3 deletions src/content/__tests__/block-tag.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import type { NodeObject } from '#tests/types'
import type {
PhrasingContentMap,
TypeExpression
TypeMetadata
} from '@flex-development/docast'
import type mdast from 'mdast'
import type * as TestSubject from '../block-tag'
Expand Down Expand Up @@ -34,9 +34,9 @@ describe('unit-d:content/blockTag', () => {
.toMatchTypeOf<NodeObject<mdast.Code>>()
})

it('should match NodeObject<TypeExpression>', () => {
it('should match NodeObject<TypeMetadata>', () => {
expectTypeOf<TestSubject.BlockTagContentMap>()
.toMatchTypeOf<NodeObject<TypeExpression>>()
.toMatchTypeOf<NodeObject<TypeMetadata>>()
})
})
})
7 changes: 6 additions & 1 deletion src/content/__tests__/content.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import type {
BlockTagContent,
DescriptionContent,
FlowContent,
PhrasingContent
PhrasingContent,
TypeExpression
} from '@flex-development/docast'
import type TestSubject from '../content'

Expand All @@ -27,4 +28,8 @@ describe('unit-d:content/content', () => {
it('should allow PhrasingContent', () => {
expectTypeOf<PhrasingContent>().toMatchTypeOf<TestSubject>
})

it('should allow TypeExpression', () => {
expectTypeOf<TypeExpression>().toMatchTypeOf<TestSubject>
})
})
43 changes: 13 additions & 30 deletions src/content/__tests__/node.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@
* @module docast/content/tests/unit-d/node
*/

import type { NodeObject } from '#tests/types'
import type { InlineTag, Root } from '@flex-development/docast'
import type {
BlockTag,
Comment,
Description,
InlineTag,
Root,
TypeExpression
} from '@flex-development/docast'
InclusiveDescendant,
Type
} from '@flex-development/unist-util-types'
import type mdast from 'mdast'
import type * as TestSubject from '../node'

describe('unit-d:content/node', () => {
Expand All @@ -27,30 +24,16 @@ describe('unit-d:content/node', () => {
})

describe('NodeMap', () => {
it('should match NodeObject<BlockTag>', () => {
expectTypeOf<TestSubject.NodeMap>().toMatchTypeOf<NodeObject<BlockTag>>()
})

it('should match NodeObject<Comment>', () => {
expectTypeOf<TestSubject.NodeMap>().toMatchTypeOf<NodeObject<Comment>>()
})

it('should match NodeObject<Description>', () => {
expectTypeOf<TestSubject.NodeMap>()
.toMatchTypeOf<NodeObject<Description>>()
})
type Skip = InclusiveDescendant<mdast.Root>
type Test = Exclude<InclusiveDescendant<Root>, Skip> | InlineTag

it('should match NodeObject<InlineTag>', () => {
expectTypeOf<TestSubject.NodeMap>().toMatchTypeOf<NodeObject<InlineTag>>()
})

it('should match NodeObject<Root>', () => {
expectTypeOf<TestSubject.NodeMap>().toMatchTypeOf<NodeObject<Root>>()
})
it('should register all docast nodes', () => {
// Arrange
type Nodes = TestSubject.NodeMap[keyof TestSubject.NodeMap]

it('should match NodeObject<TypeExpression>', () => {
expectTypeOf<TestSubject.NodeMap>()
.toMatchTypeOf<NodeObject<TypeExpression>>()
// Expect
expectTypeOf<Exclude<Test, Nodes>>().toEqualTypeOf<never>()
expectTypeOf<keyof TestSubject.NodeMap>().toEqualTypeOf<Type<Test>>()
})
})
})
Loading

0 comments on commit ccb141f

Please sign in to comment.