API リファレンス

このページでは、md2formライブラリで提供されるすべてのAPI(関数、クラス、インターフェース)について詳しく説明します。

メイン関数

parseMarkdownToForm

Markdownテキストを解析して、TypeScriptの型安全なフォーム定義オブジェクトに変換します。

function parseMarkdownToForm(markdown: string): Promise<FormDocument>

パラメータ

パラメータ必須説明
markdownstringパースするMarkdownコンテンツ

戻り値

型: Promise<FormDocument>

解析されたフォーム定義オブジェクトを返すPromiseです。

エラー

以下の場合にエラーが発生します:

  • SyntaxError: Markdownの構文が不正な場合
  • ValidationError: フォーム構造が無効な場合
  • ParseError: プロパティの値が不正な場合

使用例

基本的な使用:

import { parseMarkdownToForm } from "md2form"
 
const markdown = `
# サンプルフォーム
## セクション1
### 質問1
#type short_text
#required true
`
 
try {
  const form = await parseMarkdownToForm(markdown)
  console.log(form.title) // "サンプルフォーム"
  console.log(form.pages.length) // 1
} catch (error) {
  console.error("パースエラー:", error)
}

フロントマター付き:

const markdownWithFrontmatter = `
---
collectEmail: true
showProgressBar: true
---
# アンケートフォーム
## 基本情報
### お名前
#type short_text
#required true
`
 
const form = await parseMarkdownToForm(markdownWithFrontmatter)
console.log(form.settings?.collectEmail) // true

エラーハンドリング:

try {
  const form = await parseMarkdownToForm(invalidMarkdown)
} catch (error) {
  if (error instanceof SyntaxError) {
    console.error("Markdown構文エラー:", error.message)
  } else if (error instanceof Error) {
    console.error("パースエラー:", error.message)
  }
}

クラス

ParserEngine

内部的に使用されるパーサーエンジンクラスです。高度なカスタマイズが必要な場合に直接使用できます。

class ParserEngine {
  constructor(markdown: string)
  parse(): Promise<void>
  get form(): FormDocument
}

コンストラクタ

constructor(markdown: string)

パラメータ:

  • markdown (string): パースするMarkdownコンテンツ

メソッド

parse()

Markdownコンテンツの解析を実行します。

parse(): Promise<void>

戻り値: Promise<void> - 解析完了のPromise

エラー: 解析中にエラーが発生した場合、Promiseがrejectされます。

form (getter)

解析されたフォームオブジェクトを取得します。parse()メソッド実行後に使用してください。

get form(): FormDocument

戻り値: FormDocument - 解析されたフォーム定義

使用例

基本的な使用:

import { ParserEngine } from "md2form/src/parseEngine"
 
const engine = new ParserEngine(markdownContent)
await engine.parse()
const formData = engine.form
 
console.log("フォームタイトル:", formData.title)
console.log("ページ数:", formData.pages.length)

エラーハンドリング付き:

const engine = new ParserEngine(markdownContent)
 
try {
  await engine.parse()
  const form = engine.form
 
  // フォーム処理
  processForm(form)
} catch (error) {
  console.error("パースエラー:", error)
  // エラー処理
}

カスタム処理:

class CustomFormProcessor {
  private engine: ParserEngine
 
  constructor(markdown: string) {
    this.engine = new ParserEngine(markdown)
  }
 
  async processWithValidation(): Promise<FormDocument> {
    await this.engine.parse()
    const form = this.engine.form
 
    // カスタムバリデーション
    this.validateForm(form)
 
    return form
  }
 
  private validateForm(form: FormDocument): void {
    if (!form.title) {
      throw new Error("フォームタイトルが必要です")
    }
 
    if (form.pages.length === 0) {
      throw new Error("最低1つのページが必要です")
    }
  }
}

型定義のインポート

md2formからすべての型定義を直接インポートできます:

// メイン型のインポート
import type { FormDocument, FormSettings, Page, FormElement, ElementType } from "md2form"
 
// 個別の質問タイプのインポート
import type {
  ShortText,
  LongText,
  NumberField,
  EmailField,
  PhoneField,
  DropdownField,
  RadioField,
  CheckboxField,
  DateField,
  TimeField,
  RatingField,
  LikertField,
  MatrixField,
  ScaleField,
  FileUploadField,
  SignatureField,
  MediaField,
  BooleanField,
  SectionHeader,
  UnknownElement,
} from "md2form"
 
// JSON関連型のインポート
import type { JsonValue, JsonObject, JsonArray } from "md2form"

使用例:

import { parseMarkdownToForm } from "md2form"
import type { FormDocument, ShortText } from "md2form"
 
const form: FormDocument = await parseMarkdownToForm(markdown)
 
form.pages.forEach((page) => {
  page.elements.forEach((element) => {
    if (element.type === "short_text") {
      const shortText = element as ShortText
      console.log(shortText.placeholder)
    }
  })
})

高度な使用例

カスタムパーサーの作成

import { ParserEngine } from "md2form/src/parseEngine"
import { FormDocument, FormElement } from "md2form/src/types/form.types"
 
import { ParserEngine } from "md2form/src/parseEngine"
import type { FormDocument, FormElement } from "md2form"
 
class ExtendedParser extends ParserEngine {
  private customSettings: Record<string, unknown> = {}
 
  constructor(markdown: string, settings?: Record<string, unknown>) {
    super(markdown)
    this.customSettings = settings || {}
  }
 
  async parseWithCustomLogic(): Promise<FormDocument> {
    await this.parse()
    const form = this.form
 
    // カスタム後処理
    return this.applyCustomTransforms(form)
  }
 
  private applyCustomTransforms(form: FormDocument): FormDocument {
    // カスタムロジックの適用
    const transformedForm: FormDocument = {
      ...form,
      pages: form.pages.map((page) => ({
        ...page,
        elements: page.elements.map((element) => this.transformElement(element)),
      })),
    }
 
    return transformedForm
  }
 
  private transformElement(element: FormElement): FormElement {
    // 要素レベルのカスタム変換
    if (element.type === "short_text" && this.customSettings.autoRequired) {
      return { ...element, required: true }
    }
 
    return element
  }
}

バッチ処理用のユーティリティ

import { parseMarkdownToForm } from "md2form"
import type { FormDocument } from "md2form"
 
class FormBatchProcessor {
  private results: Array<{
    success: boolean
    filename?: string
    form?: FormDocument
    error?: string
  }> = []
 
  async processFiles(files: Array<{ name: string; content: string }>): Promise<void> {
    const promises = files.map((file) => this.processSingleFile(file))
    await Promise.allSettled(promises)
  }
 
  private async processSingleFile(file: { name: string; content: string }): Promise<void> {
    try {
      const form = await parseMarkdownToForm(file.content)
      this.results.push({
        success: true,
        filename: file.name,
        form,
      })
    } catch (error) {
      this.results.push({
        success: false,
        filename: file.name,
        error: error instanceof Error ? error.message : "Unknown error",
      })
    }
  }
 
  getResults(): typeof this.results {
    return this.results
  }
 
  getSuccessCount(): number {
    return this.results.filter((r) => r.success).length
  }
 
  getErrorCount(): number {
    return this.results.filter((r) => !r.success).length
  }
}

エラー処理

エラーの種類

md2formでは以下のタイプのエラーが発生する可能性があります:

SyntaxError

Markdown構文に問題がある場合:

try {
  const form = await parseMarkdownToForm("Invalid markdown")
} catch (error) {
  if (error instanceof SyntaxError) {
    console.error("構文エラー:", error.message)
    // 構文修正の提案など
  }
}

ValidationError

フォーム構造が無効な場合:

// カスタムバリデーションエラーの例
class ValidationError extends Error {
  constructor(
    message: string,
    public details?: any,
  ) {
    super(message)
    this.name = "ValidationError"
  }
}

ParseError

プロパティ値の解析に失敗した場合:

// プロパティパースエラーの処理
try {
  const form = await parseMarkdownToForm(markdown)
} catch (error) {
  if (error.message.includes("property")) {
    console.error("プロパティエラー:", error.message)
    // プロパティ修正の提案
  }
}

エラーハンドリングのベストプラクティス

import { parseMarkdownToForm } from "md2form"
import type { FormDocument } from "md2form"
 
async function robustParseForm(markdown: string): Promise<{
  success: boolean
  form?: FormDocument
  error?: string
  warnings?: string[]
}> {
  const warnings: string[] = []
 
  try {
    // 事前チェック
    if (!markdown.trim()) {
      return {
        success: false,
        error: "Markdownコンテンツが空です",
      }
    }
 
    // パース実行
    const form = await parseMarkdownToForm(markdown)
 
    // 後処理チェック
    if (form.pages.length === 0) {
      warnings.push("ページが存在しません")
    }
 
    return {
      success: true,
      form,
      warnings: warnings.length > 0 ? warnings : undefined,
    }
  } catch (error) {
    return {
      success: false,
      error: error instanceof Error ? error.message : "Unknown error",
    }
  }
}

パフォーマンス考慮事項

メモリ使用量

大きなMarkdownファイルを処理する場合のメモリ効率:

// メモリ効率的な処理
async function processLargeForm(markdown: string): Promise<FormDocument> {
  // チャンク処理やストリーミングが必要な場合の実装例
  const chunkSize = 10000 // 10KB chunks
 
  if (markdown.length > chunkSize * 10) {
    console.warn("Large markdown detected, consider processing in chunks")
  }
 
  return await parseMarkdownToForm(markdown)
}

並列処理

// Worker Threadsを使用した並列処理の例
import { Worker, isMainThread, parentPort, workerData } from "worker_threads"
 
if (isMainThread) {
  // メインスレッド
  async function parseFormsInParallel(markdowns: string[]): Promise<FormDocument[]> {
    const workers = markdowns.map((markdown) => {
      return new Promise<FormDocument>((resolve, reject) => {
        const worker = new Worker(__filename, {
          workerData: { markdown },
        })
 
        worker.on("message", resolve)
        worker.on("error", reject)
      })
    })
 
    return Promise.all(workers)
  }
} else {
  // ワーカースレッド
  import { parseMarkdownToForm } from "md2form"
 
  parseMarkdownToForm(workerData.markdown)
    .then((result) => parentPort?.postMessage(result))
    .catch((error) => parentPort?.postMessage({ error: error.message }))
}

制限事項

現在の制限

  1. ネストした見出し: 4レベル以上の見出しはサポートされていません
  2. プロパティ値: 一部の特殊文字でエスケープが必要です
  3. ファイルサイズ: 非常に大きなファイル(>10MB)では性能が低下する可能性があります
  4. 並行処理: 同一インスタンスでの並行パースはサポートされていません

回避策

// 大きなファイルの分割処理
function splitLargeMarkdown(markdown: string, maxSize: number = 100000): string[] {
  if (markdown.length <= maxSize) {
    return [markdown]
  }
 
  // セクション単位で分割
  const sections = markdown.split(/^## /m)
  // 分割ロジックの実装...
 
  return sections
}

デバッグユーティリティ

デバッグ情報の取得

import type { FormDocument } from "md2form"
 
function getParseDebugInfo(form: FormDocument): {
  elementCount: number
  typeDistribution: Record<string, number>
  requiredCount: number
  settingsUsed: string[]
} {
  let elementCount = 0
  let requiredCount = 0
  const typeDistribution: Record<string, number> = {}
 
  form.pages.forEach((page) => {
    page.elements.forEach((element) => {
      elementCount++
 
      if (element.required) requiredCount++
 
      typeDistribution[element.type] = (typeDistribution[element.type] || 0) + 1
    })
  })
 
  const settingsUsed = form.settings ? Object.keys(form.settings) : []
 
  return {
    elementCount,
    typeDistribution,
    requiredCount,
    settingsUsed,
  }
}

次のステップ

APIリファレンスを理解したら、以下のページで実践的な知識を深めてください:

バージョン情報

このAPIリファレンスは md2form v1.0.1 に基づいています。最新の変更については、プロジェクトのCHANGELOGを確認してください。