actionbook-core 0.8.0
Install from the command line:
Learn more about npm packages
$ npm install @sendbird/actionbook-core@0.8.0
Install via package.json:
"@sendbird/actionbook-core": "0.8.0"
About this version
Actionbook 문서의 프레임워크 독립적 코어 라이브러리.
Tiptap/ProseMirror에 종속되지 않는 자체 AST 모델, 마크다운 파서/시리얼라이저, Jinja 조건식 평가기, 그리고 구조적 편집 Operation 시스템을 제공합니다.
기존 Actionbook 에디터의 문서 모델은 ProseMirror 스키마에 강하게 결합되어 있어서:
- 서버 사이드에서 문서를 파싱/검증할 수 없음
- 에디터를 교체하려면 데이터 모델까지 함께 바꿔야 함
- Jinja 프리뷰 등 부가 기능이 에디터 DOM에 의존
이 라이브러리는 순수 TypeScript로 작성되어 브라우저, Node.js, 서버리스 환경 어디서든 동작합니다.
import {
parseMarkdown,
serializeToMarkdown,
fromProseMirrorJSON,
validate,
doc, paragraph, text, bold, resourceTag, jumpPoint,
} from '@sb/actionbook-core';
// 마크다운 파싱
const ast = parseMarkdown('# Title\n\nUse {{tool:t1:My Tool}} at ^START^');
// 빌더로 직접 생성
const manual = doc(
paragraph(text('Hello '), text('bold', [bold()]), resourceTag('tool', 't1', 'Tool')),
);
// 스키마 검증
const errors = validate(ast); // [] 이면 정상
// 마크다운 출력
const md = serializeToMarkdown(ast);
// ProseMirror JSON 변환 (기존 editor_data 호환)
const ast2 = fromProseMirrorJSON(existingEditorData);| 모듈 | 설명 |
|---|---|
ast/ |
타입 정의, 빌더, 순회, 경로 주소 체계 |
schema/ |
AST 구조 검증 (URL 프로토콜 allowlist 포함) |
markdown/ |
mdast 기반 파서/시리얼라이저 + 커스텀 구문 플러그인 |
json/ |
v3 포맷 직렬화 + 레거시 자동 감지 역직렬화 |
compat/ |
ProseMirror JSONContent → AST 변환 |
operations/ |
구조적 편집 (Insert/Delete/Replace + undo 지원) |
jinja/ |
순수 텍스트 기반 Jinja 블록 파서 + 안전한 조건식 평가기 |
utils/ |
리소스 태그 추출, 중복 Jump Point 탐지 |
cd libs/actionbook-core
npx vitest run12개 파일, 206개 테스트. 커버리지: AST 빌더/순회, 마크다운 roundtrip, ProseMirror 호환, 스키마 검증, Jinja 평가기 보안 케이스, Operation 타입 안전성, 역직렬화 경계, URL 새니타이제이션.
이 라이브러리는 신뢰되지 않는 입력(사용자가 편집한 마크다운, 외부에서 전달된 editor_data)을 처리하도록 설계되었습니다.
| 위협 | 대응 |
|---|---|
| Jinja 조건식을 통한 임의 코드 실행 |
new Function / eval 제거. 재귀 하강 파서로 화이트리스트 연산자만 평가 |
| 악의적 AST 주입 (malformed editor_data) | 모든 역직렬화 경계에서 validate() 강제 적용 |
javascript: URL을 통한 XSS |
파서, PM 변환기, 스키마 검증 3중 차단 (http/https/mailto/tel 만 허용) |
| 깊게 중첩된 입력으로 stack overflow | 모든 재귀 함수에 MAX_DEPTH 가드 (128) |
| Operation으로 잘못된 AST 생성 | 부모-자식 타입 매트릭스 검증 + 경로 유효성 체크 |
이 라이브러리는 독립 모듈로 동일성 테스트만 완료된 상태입니다. 기존 에디터 코드를 실제로 교체하는 작업은 아직 수행되지 않았으며, 점진적으로 진행할 계획입니다.
교체 대상:
-
converters.ts→actionbookToAST() -
processResourceTags.ts→ 파서가 직접 노드 생성하므로 삭제 가능 -
editorConverter.ts→parseMarkdown()+serializeToMarkdown() -
JinjaPreview/→jinja/모듈
기존: tiptap-markdown (markdown-it 기반) → 이 라이브러리: mdast (micromark 기반)
대부분의 마크다운에서 동일한 결과를 내지만, edge case에서 차이가 발생할 수 있습니다:
- Loose/tight list 판단: 빈 줄이 포함된 리스트의 처리 방식이 다를 수 있음
- 리스트 들여쓰기: 2칸 vs 4칸 인식 차이
- HTML 인라인: 이 라이브러리는 HTML을 지원하지 않음 (설계 의도)
완화 방안: 실제 프로덕션 데이터에서 추출한 마크다운 fixture를 추가하여 차이를 조기에 발견해야 합니다.
안전성을 위해 재귀 하강 파서를 사용하므로, Jinja2의 전체 표현식 문법을 지원하지 않습니다.
지원됨: ==, !=, <, >, <=, >=, and, or, not, in, is, is not, 괄호, 문자열/숫자/불리언/None 리터럴, 점 표기법 변수
미지원:
- 필터 (
value | upper,items | length) - 함수 호출 (
len(items),range(10)) - 리스트/딕셔너리 리터럴 (
[1, 2],{"k": "v"}) - 삼항 (
"a" if cond else "b") -
not in연산자 - 슬라이싱 (
items[0])
실제 Actionbook에서 사용 중인 조건식이 이 범위를 넘는다면 evaluator 확장이 필요합니다.
- 노드 단위 편집만 가능: 텍스트 노드 내부의 문자 레벨 편집(split/merge)은 미지원
-
동시성 미지원: CRDT/OT 변환 로직 없음.
NodePath+Transaction구조가 확장 포인트로 설계되어 있지만 실제 conflict resolution은 없음 - 빈 컨테이너 허용: 모든 listItem을 삭제한 후 빈 bulletList가 남는 등의 의미적 무결성은 검증하지 않음 (schema validation에서는 잡힘)
micromark + mdast-util 생태계 의존성이 추가됨. 루트 프로젝트가 이미 remark-gfm을 쓰고 있어 중복은 적을 것으로 예상하지만, 실제 tree-shaking 후 번들 크기 측정은 아직 하지 않았습니다.
- 프로덕션 fixture 확보: 실제 고객 Actionbook 데이터에서 마크다운 + PM JSON 쌍을 추출하여 동일성 테스트 보강
- 기존 코드 점진적 교체: 가장 리스크가 낮은 읽기 전용 경로(프리뷰, 내보내기)부터 이 라이브러리로 전환
- 번들 크기 측정: Vite 빌드에서의 실제 기여도 확인
- actionbook-renderer: 자체 AST를 입력으로 받는 React 읽기 전용 렌더러. 프리뷰에 먼저 적용
-
Jinja evaluator 확장: 필터,
not in, 리스트 리터럴 등 실제 사용되는 패턴 추가 - 서버 사이드 검증: Node.js 서버에서 마크다운 파싱/Jinja 변수 추출 수행
- actionbook-editor: 자체 AST + Operation 기반의 편집 가능한 에디터
- CRDT 협업 편집: Operation 모델 위에 Yjs/Automerge 어댑터
-
History 시스템:
Transaction+invertOperation()기반 undo/redo 스택
| 리스크 | 가능성 | 영향 | 완화 |
|---|---|---|---|
| remark↔markdown-it 파싱 차이로 데이터 깨짐 | 중간 | 높음 | 프로덕션 fixture 테스트, normalize 함수, 이중 실행 비교 |
| Jinja evaluator가 실제 사용 패턴을 커버 못함 | 낮음 | 중간 | 실사용 조건식 수집 → tokenizer/parser 확장 |
| 번들 크기 증가 | 낮음 | 낮음 | tree-shaking 확인, lazy import 검토 |
^id^ 와 기존 에디터의 caret 충돌 |
낮음 | 낮음 | 알파벳+언더스코어 제한으로 범위 축소 |
Details
- actionbook-core
-
sendbird
- 5 months ago
- 35 dependencies
Assets
- actionbook-core-0.8.0.tgz
Download activity
- Total downloads 2
- Last 30 days 0
- Last week 0
- Today 0