npm package: @makecode/template-manager
Description: 템플릿 관리
Author: sung-min
Latest version: 1.0.0

# @makecode/template-manager

`@makecode/template-manager`는 HTML 템플릿을 파싱하고 렌더링하기 위한 JavaScript/TypeScript 라이브러리입니다. 이 라이브러리를 통해 커스텀 태그를 정의하고, 동적으로 데이터를 주입하여 HTML을 생성할 수 있습니다. 템플릿에 기반하여 효율적인 UI 구성을 지원하며, 다양한 사용 사례에 대응하기 쉽도록 설계되었습니다.

## 설치

`npm` 또는 `yarn`을 이용하여 설치할 수 있습니다.

```sh
npm install @makecode/template-manager
```

또는

```sh
yarn add @makecode/template-manager
```

## 사용법

### 기본 사용 예시

```typescript
import templateManager from '@makecode/template-manager';

// 커스텀 엘리먼트 정의용 템플릿
const defineTemplate = `
  <p>Use the <strong>{{=power}}</strong>, {{title}}!</p>
  <template-people>
    <p class="{{=test}}">{{title}}</p>
    <template-deep>
      <div>{{=ysm}}</div>
      <template-haha>
        {{=ysm}}
      </template-haha>
    </template-deep>
    <template-hidden>
      <p>This will not appear.</p>
      {{=test}}
    </template-hidden>
  </template-people>
  <p>{{=event}} ysm</p>
`;

let defineData = {
  power: 'Force',
  title: 'Jedi',
  people: {
    test: 'warrior',
    title: 'Luke Skywalker',
    deep: { ysm: 'Skywalker', haha: { ysm: 'Master' } },
    hidden: { test: '성공!' },
  },
  event: 'Victory',
};

const { contents, html } = templateManager.define(defineTemplate, defineData, {
  onRender: element => {
    if (element.tagName.toLowerCase() === 'template-deep') {
      element.style.color = 'red'; // 특정 태그 스타일 변경
    }
  },
});

document.body.innerHTML += html;
```

위 코드에서는 템플릿에 따라 커스텀 태그를 정의하고, 데이터와 함께 렌더링합니다. 각 커스텀 태그는 HTML 엘리먼트로 변환되어 브라우저에서 사용할 수 있으며, `onRender` 콜백을 통해 특정 엘리먼트의 스타일을 변경할 수 있습니다.

### 동적 데이터 변경

`templateManager`는 데이터 변경을 감지하여 UI를 자동으로 갱신할 수 있습니다. 예를 들어, 아래와 같이 데이터 객체를 변경하면 렌더링된 HTML이 자동으로 갱신됩니다.

```typescript
setTimeout(() => {
  console.log('데이터 변경 시도!', contents);
  contents.people.title = 'Master Yoda';
  contents.people.test = 'Jedi Master';
}, 2000);
```

위 코드에서는 2초 후에 `people` 객체의 `title`과 `test` 속성을 변경하여 HTML이 업데이트됩니다.

### paint 사용 예시

`paint` 메서드는 배열을 포함한 데이터를 사용하여 HTML을 생성할 때 유용합니다. 예를 들어, 아래와 같은 템플릿을 사용할 수 있습니다.

```typescript
const paintTemplate = `
  <p>Use the <strong>{{=power}}</strong>, {{title}}!</p>
  <template-people>
    <p class="{{=test}}">{{title}}</p>
    <template-deep>
      <div>{{=ysm}}</div>
      <template-haha>
        {{=ysm}}
      </template-haha>
    </template-deep>
  </template-people>
  <p>{{=event}} ysm</p>
`;

console.log(
  'paint',
  templateManager.paint(paintTemplate, {
    power: 'Force',
    title: 'Jedi',
    people: [
      {
        test: 'warrior',
        title: 'Luke Skywalker',
        deep: { ysm: 'Skywalker', haha: { ysm: 'Master' } },
      },
      {
        test: 'fighter',
        title: 'Leia Organa',
        deep: { ysm: 'Organa', haha: null },
      },
    ],
    event: 'Victory',
  }),
);
```

### 주요 메서드 설명

- **`parse(template: string): Parse`**: 템플릿을 파싱하여 트리를 생성합니다.
- **`render(template: string, contents: Record<string, any>): TreeNode[]`**: 파싱된 템플릿에 데이터를 적용하여 트리 노드를 생성합니다.
- **`paint(template: string, contents: Record<string, any>): string`**: 트리 노드를 HTML 문자열로 변환합니다.
- **`define(template: string, contents: Record<string, any>, options?: { onChangeContents?: Function, onRender?: Function }): { contents: Record<string, any>, html: string }`**: 템플릿을 정의하고 커스텀 엘리먼트를 등록합니다.