# Eleventy

> Nunjucks, Liquid, Markdown 템플릿에서 Ikiform 폼을 렌더링하는 Eleventy 쇼트코드. 폼 ID는 전역 데이터에 둡니다.

Eleventy는 정적 HTML을 출력하므로 클라이언트 JavaScript 없이 폼이 POST됩니다. 쇼트코드를 쓰면 마크업을 한곳에 두고 Nunjucks, Liquid, Markdown 파일에서 똑같이 쓸 수 있습니다.

## 설정하기

### 1단계: 쇼트코드 추가하기

`eleventy.config.js`:

```js
const escape = (value) => String(value).replace(/[&<>"']/g, (char) => `&#${char.charCodeAt(0)};`);

export default function (eleventyConfig) {
  eleventyConfig.addShortcode("ikiform", (formId, thanks = "", subject = "") =>
    [
      `<form class="ikiform" action="https://ikiform.com/f/${encodeURIComponent(formId)}" method="post">`,
      '<label>Email <input name="email" type="email" autocomplete="email" required></label>',
      '<label>Message <textarea name="message" rows="5"></textarea></label>',
      thanks && `<input type="hidden" name="_redirect" value="${escape(thanks)}">`,
      subject && `<input type="hidden" name="_subject" value="${escape(subject)}">`,
      '<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden>',
      '<button type="submit">Send</button>',
      "</form>",
    ]
      .filter(Boolean)
      .join("\n"),
  );
}
```

- 줄 사이에 빈 줄이 없도록 일부러 이어 붙였습니다. Markdown에서는 빈 줄이 HTML 블록을 끝내므로, 나머지 폼이 텍스트로 처리됩니다.
- ES 모듈 문법을 사용합니다. `package.json`에 `"type": "module"`이 없다면 파일 이름을 `eleventy.config.mjs`로 하세요.

### 2단계: 폼 ID를 전역 데이터에 두기

`_data/ikiform.js`:

```js
export default {
  formId: process.env.IKIFORM_FORM_ID ?? "frm_xxxxxxxxxxxxxxxx",
  thanks: "https://example.com/thanks/",
};
```

전역 데이터는 모든 템플릿에서 `ikiform`으로 사용할 수 있습니다. Ikiform은 다른 리디렉션을 무시하므로 감사 페이지 URL은 `https:` 절대 URL이어야 합니다.

### 3단계: 사용하기

`contact.md`:

```text
---
title: Contact
---

Questions about pricing? Write to us.

{% ikiform ikiform.formId, ikiform.thanks, "Pricing question" %}
```

Markdown 파일은 기본적으로 Liquid로 처리되므로 태그를 그대로 쓰면 작동합니다. 태그는 한 줄에 단독으로 두고 공백 네 칸으로 들여 쓰지 마세요. 그러면 Markdown이 코드 블록으로 렌더링합니다. 같은 태그가 `.njk`와 `.liquid` 파일에서도 작동합니다.

`_redirect`는 폼의 허용 도메인에 여러분의 사이트가 포함된 경우에만 따릅니다. [_redirect 규칙](https://ikiform.com/ko/docs/html.md#redirect-rules)을 참고하세요.

## 허용 도메인

프로덕션과 각 미리보기 호스트를 등록하세요. Eleventy 사이트는 주로 Netlify나 Cloudflare Pages에 배포하며, 두 곳은 미리보기를 다르게 처리합니다.

| 폼이 실행되는 곳 | Allowed domains에 추가할 값 |
| --- | --- |
| `npx @11ty/eleventy --serve` | `localhost`. `http://localhost:8080`과 일치합니다. Ikiform은 포트가 아니라 호스트 이름만 비교합니다. |
| 여러분의 도메인 | `example.com`, `www.example.com`도 포함 |
| Netlify | `your-site.netlify.app`. 배포 미리보기(`deploy-preview-12--your-site.netlify.app`)와 브랜치 배포(`branch--your-site.netlify.app`)는 하위 도메인이 아니므로, 테스트하는 동안 정확한 미리보기 호스트를 추가하세요. |
| Cloudflare Pages | `your-project.pages.dev`. `abc123.your-project.pages.dev` 같은 미리보기 URL은 하위 도메인이므로 이미 일치합니다. |

- `netlify.app`이나 `pages.dev`만 단독으로 추가하지 마세요. 다른 사람의 사이트를 포함해 그 호스트의 모든 사이트가 일치하게 됩니다.

## 테스트 체크리스트

1. 개발 서버를 실행하고 페이지 소스를 보세요. 폼은 `<pre><code>` 블록 안이 아니라 일반 HTML이어야 합니다.
2. 허용 도메인에 `localhost`를 넣고 로컬에서 제출한 뒤 제출이 Ikiform에 표시되는지 확인하세요.
3. 미리보기를 배포하고 미리보기 호스트에서 다시 제출하세요.
4. 프로덕션에서 제출하고 감사 페이지로 이동하는지 확인하세요.

## 문제 해결

| 증상 | 원인 | 해결 |
| --- | --- | --- |
| 폼이 페이지에 코드로 표시됨 | Markdown 파일에서 쇼트코드가 공백 네 칸으로 들여 쓰여 있음 | 태그를 줄의 맨 앞으로 옮기세요. |
| 폼의 절반이 문단으로 렌더링됨 | 쇼트코드 출력에 빈 줄이 있어 Markdown의 HTML 블록이 끝남 | 위 설정처럼 빈 줄 없이 줄을 이어 붙이세요. |
| Eleventy를 시작할 때 `SyntaxError: Unexpected token 'export'` | CommonJS 프로젝트에서 설정 파일이 ES 모듈 문법을 사용함 | `eleventy.config.mjs`로 이름을 바꾸거나 `package.json`에 `"type": "module"`을 추가하세요. |
| Nunjucks나 Liquid가 `ikiform` 태그를 찾지 못함 | Eleventy가 설정 파일을 불러오지 않음 | 파일이 프로젝트 루트에 있고 이름이 `eleventy.config.js` 또는 `.mjs`인지 확인하세요. |
| 제출이 `origin_mismatch`와 함께 스팸 필터에 들어감 | POST한 페이지가 폼의 허용 도메인에 없음 | 위 표의 호스트를 추가하세요. **Reject**를 골랐다면 같은 POST가 대신 `403 origin_not_allowed`를 받습니다. |

## 관련 문서

- [Hugo](https://ikiform.com/ko/docs/guides/hugo.md): 파셜과 콘텐츠 파일용 쇼트코드.
- [Jekyll](https://ikiform.com/ko/docs/guides/jekyll.md): 인클루드와 GitHub Pages 설정.
- [HTML 폼](https://ikiform.com/ko/docs/html.md): 리디렉션, 예약 필드, 허니팟.
- [허용 도메인](https://ikiform.com/ko/docs/spam.md#allowed-domains): 출처를 비교하는 방식과 불일치 시 동작.
