도트체이닝 인터페이스 정의 - ChoDragon9/posts GitHub Wiki

Spec

  • 사용자에게 노출 될 인터페이스이다.
  • DescriptorExporter로 이뤄진다.
  • lift를 통해 Immutable State를 공유한다.

Spec.js

import * as descriptor from './descriptor'
import * as exporter from './exporter'
import {immutable, lift, chainLift} from '../helper/index'

export default (state = {}) => {
  const immutableState = immutable(state)
  return {
    ...chainLift(immutableState, descriptor),
    ...lift(immutableState, exporter)
  }
}

lift

  • 모든 오퍼레이터에 Wrapper를 씌운다.
  • Wrapper를 통해 호출되면 사용자가 전달한 인자앞에 Immutable State를 공유한다.

helper/index.js

export const chainLift = (state, operators) => {
  const newOperators = {}
  for (const [name, cb] of Object.entries(operators)) {
    newOperators[name] = (...args) => Spec(cb(state, ...args))
  }
  return newOperators
}
export const lift = (state, operators) => {
  const newOperators = {}
  for (const [name, cb] of Object.entries(operators)) {
    newOperators[name] = (...args) => cb(state, ...args)
  }
  return newOperators
}

Descriptor

  • Hypertext의 속성을 정의할 수 있는 오퍼레이터를 제공한다.
  • Descriptor의 각 오퍼레이터는 Spec의 펙토리 메서드이며, 항상 새로운 Spec을 반환한다.
  • operator(state: ImmutableState, [...arguments]) : ImmutableState 형태로 추가한다.
    • 사용자에게는 operator(...arguments) : Spec 형태로 사용된다.

Descriptor.js

export { on } from './on'
export { className } from './className'
export { children } from './children'
export { spec } from './spec'

on.js

import {merge} from '../../helper/index'
export const on = (state, eventName, listener) => {
  return merge(state, {[eventName]: listener})
}

Exporter

  • Hypertext를 데이터 타입으로 변환해주는 오퍼레이터를 제공한다.
  • operator(state: ImmutableState, [...arguments]) : DataType 형태로 추가한다.
    • 사용자에게는 operator(...arguments) : DataType 형태로 사용된다.
    • 예) toString() : String, toJSON() : Object, toDOM() : HTMLElement

Exporter.js

export { toJSON } from './toJSON'
export { toDOM } from './toDOM'
export { toString } from './toString'

toJSON.js

export const toJSON = state => JSON.parse(JSON.stringify(state))

Hypertext

  • HTMLElement 객체 생성 오퍼레이터를 제공한다.
  • Hypertext의 각 오퍼레이터는 Spec의 펙토리 메서드이며, 항상 새로운 Spec을 반환한다.
  • div() : Spec

Hypertext.js

export { div } from './div'
export { p } from './p'
export { text } from './text'

div.js

import Spec from '../Spec/index'
export const div = () => Spec({nodeName: 'div'})

사용예제

import Spec from './Spec'
import { div, p, text } from './Hypertext'

const spec = Spec()
  .on('click', () => {})
  .className('table table-border')
const child = [
  div(),
  p(),
  text('Hello world')
]
const tag = div().spec(spec).children(...child)
const data = tag.toJSON()

spec

{
  spec: {
    className: 'table table-border',
    click () {}
  }
}

children

{
  children: [
    {nodeName: 'div'},
    {nodeName: 'p'},
    {nodeName: 'text', value: 'Hello World'}
  ]
}

data

{
  nodeName: 'div',
  children: [
    {nodeName: 'div'},
    {nodeName: 'p'},
    {nodeName: 'text', value: 'Hello World'}
  ],
  spec: {
    className: 'table table-border'
  }
}