埋め込み

スクリプト1行で自分のサイトやアプリにエディタを組み込めます。Plusのライセンスキーで透かしが消えます。

導入

下のスニペットを貼るだけです。依存なしの82KB単一ファイルで動きます。

<div id="typdit-editor"></div>
<script src="https://typdit.com/embed/v1.js"></script>
<script>
  const editor = Typdit.create(document.getElementById('typdit-editor'), {
    placeholder: 'Write here',
    licenseKey: 'YOUR_KEY',
    onChange: (snapshot) => console.log(snapshot),
  });
</script>

エディタ画面からそのまま持ち出す

設置コードを手で書く必要はありません。エディタ画面でモードとテーマを好みに合わせて下にスクロールすると、その設定がそのまま書かれた設置コードがあります。既定値と同じオプションは書かれないので、何が特別な設定かが一目で分かります。

文書ごとコピーを押すと、今画面にある内容が snapshot オプションとして一緒に入ります。テンプレートを開いて骨組みを確認し、その骨組みごと持ち出したいときに使います。

オプション一覧

すべて Typdit.create(element, options) の第2引数で渡します。全項目が省略可能で、既定値は表のとおりです。

オプション説明
snapshot初期文書(JSONスナップショット、下の形式の節を参照)。省略時は空文書
theme: 'light' | 'dark'テーマ(既定 light)
mode: 'notion'Notionスタイルのプリセット: ツールバーを隠しブロックハンドルを有効化(下の節を参照)。既定は classic
handles: trueブロックハンドルの個別トグル(mode プリセットより優先)
writingMode: 'paper'書き方モード。plain, focus, book, paper, essay, script, techdoc のいずれか、またはプリセットオブジェクト。組み方と計量、目次、脚注、台本の流れがまとめて変わります
writingMode: { id, extends }内蔵モードの上に数項目だけ上書きして独自モードを作ります。extends を外すと何も入っていない土台から始まります
writingLabelsモードUIの文言差し替え(計量名, 目次, 脚注, 目標)。部分指定可、未指定は英語の既定値
writingSlashLabelsモード専用スラッシュ項目の文言(脚注, 台本ブロック)
handleLabelsブロックハンドルの文言を置き換え(部分指定可)
toolbar: false上部ツールバーを非表示(既定は表示)
menus: falseスラッシュコマンドと選択バブルメニューを無効化(既定は有効)
markdown: false# 見出しや - リストなどのMarkdown入力を無効化(既定は有効)
typography: false曲がった引用符と三点リーダーの自動置換を無効化(既定は有効)
placeholder空文書に表示するヒント文
autofocus: true生成直後にエディタへフォーカス(既定はオフ)
toolbarLabelsツールバーの文言を置き換え(部分指定可、下の節を参照)
licenseKeyPlusライセンスキー。ドメイン検証後に透かしを除去
onChange(snapshot)内容が変わるたびに最新スナップショットを渡す
onRequestImage()画像アップローダーのフック。{src, alt?} を resolve で挿入、null でキャンセル。未指定ならツールバーはURL入力にフォールバック
onRequestFile()ファイル添付のフック。{src, name?, size?} を返す。指定した場合のみファイルボタンが表示される
onRequestVideo()動画アップロードのフック。{src} を返す。指定すると動画リンク入力の横にアップロードボタンが追加される(リンク入力は常に可能)

Notionスタイルモード

mode: 'notion' はツールバーを隠し、ブロックハンドルを有効にします。ブロックにマウスを乗せると左に追加(+)とメニュー(⋮⋮)ボタンが現れ、メニューから上下移動・複製・削除・ブロック変換ができます。書式はスラッシュコマンドと選択バブルメニューでそのまま使えます。

ツールバーがない場合、画像・動画・ファイルの挿入項目はスラッシュメニューからも外れます(入力UIがツールバー側にあるため)。ハンドルと添付の両方が必要なら toolbar: true を併せて渡してください。ハンドルとツールバーは共存できます。

Typdit.create(el, {
  mode: 'notion',
  handleLabels: { moveUp: '위로 이동', moveDown: '아래로 이동', delete: '삭제' },
});

インスタンスメソッド

Typdit.create() が返すハンドルで文書を読み書きします。保存は完全にホストサイト側の役割です。

メソッド説明
getSnapshot()現在の文書をJSONスナップショットで返す
setSnapshot(json)スナップショットで文書全体を置き換える(読み込み)
getText()書式なしのプレーンテキストを返す(検索索引・文字数カウント用)
focus()エディタへフォーカスを移す
destroy()エディタを除去しリスナーを解除。SPAで画面を離れるときに呼ぶ
versionSDKバージョン文字列(現在 1.0.0)

スナップショットの形式

スナップショットはそのまま保存してそのまま返せばよいフラットなJSONです。text の1行が blocks の1項目に1:1で対応し、marks は text 基準のオフセット区間です。未知のブロック・マークタイプは読み込み時に無視されるため、新しいバージョンが作ったスナップショットを古いバージョンで開いても壊れません。

{
  "version": 1,
  "text": "제목\n첫 문단입니다.",
  "blocks": [
    { "type": "heading", "attrs": { "level": 1 } },
    { "type": "paragraph" }
  ],
  "marks": [
    { "type": "bold", "from": 3, "to": 7 }
  ]
}

自動保存をつなぐ

onChange は打鍵のたびに呼ばれます。サーバー保存はデバウンスをかけ、手が止まってから1回だけ送るのが一般的です。

let timer;
const editor = Typdit.create(el, {
  onChange: (snapshot) => {
    clearTimeout(timer);
    timer = setTimeout(() => {
      fetch('/api/save', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(snapshot),
      });
    }, 800);
  },
});

画像・ファイルアップロード連携

エディタ自身はファイルをアップロードしません。フックが選択とアップロードを担当してURLを返せば、挿入と表示はエディタが行います。フックなしでも画像はURL入力で動き、ファイルボタンは onRequestFile を渡した場合のみ表示されます。

Typdit.create(el, {
  onRequestImage: async () => {
    const file = await pickFile('image/*');   // 파일 선택 UI는 호스트 구현
    if (!file) return null;                   // null = 취소
    const src = await uploadToMyServer(file); // 업로드도 호스트 구현
    return { src, alt: file.name };
  },
  onRequestFile: async () => {
    const file = await pickFile('*/*');
    if (!file) return null;
    const src = await uploadToMyServer(file);
    return { src, name: file.name, size: file.size };
  },
  onRequestVideo: async () => {
    const file = await pickFile('video/*');
    return file ? { src: await uploadToMyServer(file) } : null;
  },
});

ツールバー文言の変更

既定の文言は英語です。toolbarLabels に変えたいキーだけを部分的に渡せば、残りは既定のままです。キー一覧: text, quote, code, divider, table, image, video, file, upload, font, fontDefault, color, highlight, none, alignLeft, alignCenter, alignRight, imageUrl, videoUrl, link, linkApply, linkRemove, undo, redo。

Typdit.create(el, {
  toolbarLabels: {
    text: '본문', quote: '인용', code: '코드', divider: '구분선',
    image: '이미지', video: '영상', link: '링크',
    undo: '되돌리기', redo: '다시 실행',
  },
});

Reactでの使い方

ref でコンテナをつかみ、マウント時に生成、アンマウント時に destroy() を呼びます。

import { useEffect, useRef } from 'react';

function TypditEditor({ onChange }) {
  const ref = useRef(null);
  useEffect(() => {
    const editor = window.Typdit.create(ref.current, { onChange });
    return () => editor.destroy();
  }, []);
  return <div ref={ref} />;
}

Vueでの使い方

onMounted で生成し、onBeforeUnmount で destroy() を呼びます。

<template><div ref="host"></div></template>

<script setup>
import { onMounted, onBeforeUnmount, ref } from 'vue';
const host = ref(null);
let editor;
onMounted(() => { editor = window.Typdit.create(host.value, {}); });
onBeforeUnmount(() => editor?.destroy());
</script>

SSRフレームワーク(Next.jsなど)での使い方

スクリプトはブラウザでのみ実行されます。サーバーレンダリング中は window がないため、クライアント専用コンポーネントでスクリプトを読み込んでから生成してください。

'use client';
import { useEffect, useRef } from 'react';

export default function Editor() {
  const ref = useRef(null);
  useEffect(() => {
    let editor;
    const s = document.createElement('script');
    s.src = 'https://typdit.com/embed/v1.js';
    s.onload = () => { editor = window.Typdit.create(ref.current, {}); };
    document.head.appendChild(s);
    return () => editor?.destroy();
  }, []);
  return <div ref={ref} />;
}

1ページに複数エディタ

Typdit.create() の呼び出しごとに独立したインスタンスが作られるため、1ページにいくつでも置けます。スタイルは初回生成時に style タグ1つだけ注入され、各インスタンスは自分のハンドルの destroy() で個別に除去します。

ライセンスと透かし

  • キーなしでも全機能が動き、下部に小さな透かしが付きます。
  • Plus購読者はエディタ画面の埋め込みカードでドメインごとのキーを発行します。キーは登録ドメインとそのサブドメインで有効です(*.example.com 表記も同じ意味)。
  • キーの期限は発行時点の購読期限と同じです。延長後はキーを再発行してください。
  • 検証に失敗してもネットワークが遮断されていても、エディタは止まりません。透かしが残るだけで、エラーも出ません。

ネットワークとCSP

  • 文書の内容はどこにも送信されません。エディタはコンテンツに関するネットワーク要求を行わず、保存は完全にホストサイト側です。
  • 唯一の要求は licenseKey 指定時の検証1回です(firestore.googleapis.com への読み取り専用)。
  • CSPを使うサイトは script-src に typdit.com を、キーを使うなら connect-src に firestore.googleapis.com を許可します。本文に入れる画像・動画は別で、その提供元を img-src・frame-src で開ける必要があります(YouTube埋め込みは youtube-nocookie.com)。
  • スタイルは td- 接頭辞クラスでスコープされた style タグ1つで注入され、ホストのCSSと混ざりません。

バージョンポリシー

/embed/v1.js はメジャーバージョンが固定されたURLです。v1 のURL内では後方互換が維持され、互換が壊れる変更は新しいURL(v2)で提供されます。読み込まれたバージョンは実行時に Typdit.version で確認できます。

次へ: AIツール →