orgapp / orgajs

parse org-mode content into AST
https://orga.js.org
MIT License
614 stars 62 forks source link

These `children` types are missing in AST #110

Open BlackGlory opened 3 years ago

BlackGlory commented 3 years ago

ListItem: https://github.com/orgapp/orgajs/blob/211df5bda9021d513c6d2121115d55f49ebf5c96/packages/orga/src/types.ts#L100-L104

Headline: https://github.com/orgapp/orgajs/blob/211df5bda9021d513c6d2121115d55f49ebf5c96/packages/orga/src/types.ts#L106-L114

Footnote: https://github.com/orgapp/orgajs/blob/211df5bda9021d513c6d2121115d55f49ebf5c96/packages/orga/src/types.ts#L52-L55

GuiltyDolphin commented 3 years ago

@BlackGlory From which AST are they missing? Do you find them missing in the result from the parser (orga), or in results from one of the other packages?

BlackGlory commented 3 years ago

@GuiltyDolphin The descendant types defined in the AST definition file types.ts are missing. The children type of these nodes is inherited from UnistParent, which is ChildNode[], and you can use Document as children, this is meaningless:

const document: Document = {
  type: 'document'
, children: []
, properties: {}
}

const item: ListItem = {
  type: 'list.item'
, indent: 2
, children: [document]
}
GuiltyDolphin commented 3 years ago

@BlackGlory Yup, it's pretty consistent throughout (in 2.4.9). In #104 I've updated some of the children types (and will continue to update them) so that they are more aligned with the specification.

BlackGlory commented 3 years ago

Rewritten an AST type definition for my project based on orga v2.4.9, if someone needs it:

import { Literal as UnistLiteral, Node, Parent } from 'unist'
export { Node, Parent } from 'unist'

interface Child {
  parent?: Parent
}

type Primitive = string | number | boolean

interface Attributes {
  [key: string]: Primitive | Record<string, Primitive>
}

interface Attributed {
  attributes: Attributes
}

interface Timestamp {
  date: Date
  end?: Date
}

interface Literal extends UnistLiteral {
  value: string
}

export type DocumentContent =
| UniversalBlockContent
| Section
| Footnote

export type SectionContent =
| UniversalBlockContent
| Section
| Headline
| Planning

export type TableContent = TableRow | TableRule

export type HeadlineContent =
| Stars
| Todo
| Priority
| Tags
| UniversalInlineContent

export type ListContent = List | ListItem

export type ListItemContent =
| ListItemBullet
| ListItemCheckbox
| UniversalInlineContent

export type UniversalBlockContent =
| Paragraph
| Block
| Drawer
| List
| Table
| HorizontalRule

export type UniversalInlineContent =
| StyledText
| Link
| FootnoteReference
| Newline

export interface Document extends Child, Parent {
  type: 'document'
  properties: Record<string, string>
  children: DocumentContent[]
}

export interface Section extends Child, Parent {
  type: 'section'
  level: number
  properties: Record<string, string>
  children: SectionContent[]
}

export interface Headline extends Child, Parent {
  type: 'headline'
  level: number

  actionable: boolean

  priority?: string

  tags?: string[]

  content: string

  children: HeadlineContent[]
}

export interface Footnote extends Child, Parent {
  type: 'footnote'
  label: string

  children: UniversalBlockContent[]
}

export interface FootnoteReference extends Child, Parent {
  type: 'footnote.reference'
  label: string
  children: UniversalInlineContent[]
}

export interface Block extends Literal, Attributed {
  type: 'block'
  name: string
  params: string[]
  value: string
}

export interface Drawer extends Literal {
  type: 'drawer'
  name: string
  value: string
}

export interface Planning extends Node {
  type: 'planning'
  keyword: string
  timestamp: Timestamp
}

export interface List extends Child, Parent, Attributed {
  type: 'list'
  indent: number
  ordered: boolean
  children: ListContent[]
}

export interface ListItem extends Child, Parent {
  type: 'list.item'
  indent: number

  tag?: string

  children: ListItemContent[]
}

export interface Table extends Child, Parent, Attributed {
  type: 'table'
  children: TableContent[]
}

export interface TableRow extends Child, Parent {
  type: 'table.row'
  children: TableCell[]
}

export interface TableCell extends Child, Parent {
  type: 'table.cell'
  children: UniversalInlineContent[]
}

export interface TableRule extends Node {
  type: 'table.hr'
}

export interface Paragraph extends Child, Parent, Attributed {
  type: 'paragraph'
  children: UniversalInlineContent[]
}

export interface HorizontalRule extends Node {
  type: 'hr'
}

export interface Newline extends Node {
  type: 'newline'
}

export interface StyledText extends Literal {
  type: 'text.plain'
      | 'text.bold'
      | 'text.verbatim'
      | 'text.italic'
      | 'text.strikeThrough'
      | 'text.underline'
      | 'text.code'
}

export interface Link extends Literal {
  type: 'link'
  protocol: string
  description?: string
  value: string
  search?: string | number
}

export interface Stars extends Node {
  type: 'stars'
  level: number
}

export interface Todo extends Node {
  type: 'todo'
  keyword: string
  actionable: boolean
}

export interface Priority extends Literal {
  type: 'priority'
  value: string
}

export interface Tags extends Node {
  type: 'tags'
  tags: string[]
}

export interface ListItemCheckbox extends Node {
  type: 'list.item.checkbox'
  checked: boolean
}

export interface ListItemBullet extends Node {
  type: 'list.item.bullet'
  ordered: boolean
  indent: number
}
BlackGlory commented 3 years ago

v3.0.0

import { Node, Parent } from 'unist'
export { Node, Parent } from 'unist'

type Primitive = string | number | boolean

interface Attributes {
  [key: string]: Primitive | Record<string, Primitive>
}

interface Attributed {
  attributes: Attributes
}

interface Timestamp {
  date: Date
  end?: Date
}

export type DocumentContent =
| UniversalBlockContent
| Section
| Footnote

export type SectionContent =
| UniversalBlockContent
| Section
| Headline
| Planning

export type TableContent = TableRow | TableRule

export type TableRowContent = TableColumnSeparator | TableCell

export type HeadlineContent =
| Stars
| Todo
| Priority
| Tags
| UniversalInlineContent

export type ListContent = List | ListItem

export type ListItemContent =
| ListItemBullet
| ListItemTag
| ListItemCheckbox
| UniversalInlineContent

export type LinkContent = 
| UniversalInlineContent
| Opening
| Closing
| LinkPath

export type PlanningContent = 
| PlanningKeyword
| PlanningTimestamp

export type FootnoteReferenceContent = 
| FootnoteLabel
| Opening
| Closing
| UniversalInlineContent

export type FootnoteContent =
| FootnoteLabel
| UniversalBlockContent

export type DrawerContent =
| DrawerBegin
| DrawerEnd
| UniversalInlineContent

export type UniversalBlockContent =
| Paragraph
| Block
| Drawer
| List
| Table
| HorizontalRule

export type UniversalInlineContent =
| Text
| Link
| FootnoteReference
| Newline

export interface Document extends Parent {
  type: 'document'
  properties: Record<string, string>
  children: DocumentContent[]
}

export interface Section extends Parent {
  type: 'section'
  level: number
  properties: Record<string, string>
  children: SectionContent[]
}

export interface Headline extends Parent {
  type: 'headline'
  level: number

  actionable: boolean

  priority?: string

  tags?: string[]

  children: HeadlineContent[]
}

export interface Footnote extends Parent {
  type: 'footnote'
  label: string

  children: FootnoteContent[]
}

export interface FootnoteReference extends Parent {
  type: 'footnote.reference'
  label?: string
  children: FootnoteReferenceContent[]
}

export interface Block extends Node, Attributed {
  type: 'block'
  name: string
  params: string[]
  value: string
}

export interface Drawer extends Node, Parent {
  type: 'drawer'
  name: string
  value: string
  children: DrawerContent[]
}

export interface DrawerBegin {
  type: 'drawer.begin'
  name: string
}

export interface DrawerEnd {
  type: 'drawer.end'
}

export interface Planning extends Node, Parent {
  type: 'planning'
  keyword: string
  timestamp: Timestamp
  children: PlanningContent[]
}

export interface List extends Parent, Attributed {
  type: 'list'
  indent: number
  ordered: boolean
  children: ListContent[]
}

export interface ListItem extends Parent {
  type: 'list.item'
  indent: number

  tag?: string

  children: ListItemContent[]
}

export interface Table extends Parent, Attributed {
  type: 'table'
  children: TableContent[]
}

export interface TableRow extends Parent {
  type: 'table.row'
  children: TableRowContent[]
}

export interface TableCell extends Parent {
  type: 'table.cell'
  children: UniversalInlineContent[]
}

export interface TableRule extends Node {
  type: 'table.hr'
}

export interface TableColumnSeparator extends Node {
  type: 'table.columnSeparator'
}

export interface Paragraph extends Parent, Attributed {
  type: 'paragraph'
  children: UniversalInlineContent[]
}

export interface HorizontalRule extends Node {
  type: 'hr'
}

export interface Newline extends Node {
  type: 'newline'
}

export interface Text extends Node {
  type: 'text'
  style?: 'bold'
        | 'verbatim'
        | 'italic'
        | 'strikeThrough'
        | 'underline'
        | 'code'
  value: string
}

export interface Link extends Parent {
  type: 'link'
  path: {
    protocol: string
    value: string
    search?: string | number
  }
  children: LinkContent[]
}

export interface LinkPath extends Node {
  type: 'link.path'
  protocol: string
  value: string
  search?: string | number
}

export interface Opening extends Node {
  type: 'opening'
  element: string
}

export interface Closing extends Node {
  type: 'closing'
  element: string
}

export interface Stars extends Node {
  type: 'stars'
  level: number
}

export interface Todo extends Node {
  type: 'todo'
  keyword: string
  actionable: boolean
}

export interface Priority extends Node {
  type: 'priority'
  value: string
}

export interface Tags extends Node {
  type: 'tags'
  tags: string[]
}

export interface ListItemCheckbox extends Node {
  type: 'list.item.checkbox'
  checked: boolean
}

export interface ListItemBullet extends Node {
  type: 'list.item.bullet'
  ordered: boolean
  indent: number
}

export interface ListItemTag extends Node {
  type: 'list.item.tag'
  value: string
}

export interface FootnoteLabel extends Node {
  type: 'footnote.label'
  label: string
}

export interface PlanningKeyword extends Node {
  type: 'planning.keyword'
  value: string
}

export interface PlanningTimestamp extends Node {
  type: 'planning.timestamp'
  value: Timestamp 
}