<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>push -f</title><description>Pull first before pushing</description><link>https://blog.euroka.moe/</link><language>ko</language><item><title>Bluesky의 ID</title><link>https://blog.euroka.moe/posts/atproto-did/</link><guid isPermaLink="true">https://blog.euroka.moe/posts/atproto-did/</guid><pubDate>Tue, 10 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;ID&lt;/h2&gt;
&lt;p&gt;내 프로필은 여기 있다. &lt;a href=&quot;https://bsky.app/profile/euroka.moe&quot;&gt;https://bsky.app/profile/euroka.moe&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;이 링크는 2개로 나눌 수 있다. bsky.app 앱뷰, euroka.moe 핸들. 그런데...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;왜 도메인 형식을 지닐까?&lt;/li&gt;
&lt;li&gt;PDS를 변경해도 핸들은 왜 같을까?&lt;/li&gt;
&lt;li&gt;핸들을 변경해도 어떻게 게시글 등은 유지될까?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;DID&lt;/h2&gt;
&lt;p&gt;이때 DID가 등장한다. Decentralized ID의 약자로, DID 종류(메서드)에 따라 탈중앙화된 식별자를 고유하게 생성한다. 180개 이상의 DID 종류가 있지만, &lt;a href=&quot;https://atproto.com/specs/did#blessed-did-methods&quot;&gt;ATProto에서 사용하는 DID&lt;/a&gt;는 두 가지가 있다.&lt;/p&gt;
&lt;h3&gt;did:web&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;did:web&lt;/code&gt;은 자신의 DID document를 &lt;code&gt;.well-known/did.json&lt;/code&gt; 경로에 둔다. &lt;code&gt;did:web:euroka.moe&lt;/code&gt;의 경우 &lt;code&gt;https://euroka.moe/.well-known/did.json&lt;/code&gt;에 있는 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!NOTE]
내 DID는 &lt;code&gt;did:web&lt;/code&gt;을 쓰지 않는다! 예시용일 뿐이니 참고 바란다.
&lt;img src=&quot;image.png&quot; alt=&quot;alt text&quot; /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;장점은,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;탈중앙화에 더 가깝다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;DNS를 신뢰해야 한다는 문제가 있지만, 이건 뭐 어쩔 수 없지 않나.
공인되고 검증된 기관이 운영한다는 것에 기대는 게 그나마 나을 것이다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;did가 직관적이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://pdsls.dev/at://did:plc:qjua73d5eq537nio2sucdaj3&quot;&gt;&lt;code&gt;did:plc:qjua73d5eq537nio2sucdaj3&lt;/code&gt;&lt;/a&gt;와 &lt;code&gt;did:web:euroka.moe&lt;/code&gt; 중 기억하기 쉬운 것을 고르라 하면 당연히 후자 아닌가?&lt;/p&gt;
&lt;p&gt;하지만 단점이 상당하다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;도메인의 &lt;code&gt;.well-known/did.json&lt;/code&gt; 접근에만 의존한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;도메인 만료, 호스팅 업체의 변덕, 레코드 작성 실수, 모든 것은 DID document의 제어권 유실로 이어진다.
그리고 DID document의 제어권 유실은 signing 키나 PDS 변경, 핸들(DID document의 &lt;code&gt;alsoKnownAs&lt;/code&gt; 값) 등을 불가능하게 만든다.
HTTPS 인증서 주던 CA가 터졌다? 다른 CA에서 인증서 받아오기 전까진, DID document는 다른 사람들에게 보이지 않게 되고, DID document가 없으니 존재하지 않는 자가 된다. 게시글, 팔로우 기록, 등등. 이것들은 존재하지 않는 사람이 한 것으로 나온다.&lt;/p&gt;
&lt;h3&gt;did:plc&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;did:plc&lt;/code&gt;는 제일 간결하고 탈중앙화는 아니지만 타협적인 방법이다. &lt;a href=&quot;https://plc.directory/&quot;&gt;PLC Dictionary&lt;/a&gt;라는 중앙화된 원장에 저장한다. 그리고 이걸 &lt;a href=&quot;https://web.plc.directory/api/redoc&quot;&gt;REST API로 모두에게 공개&lt;/a&gt;한다. 감사 로그와 키 서명 검증을 통하여 투명성을 확보하지만, 그렇다고 완전히 염려가 없는 것은 아니다. 하지만, 이는 매우 큰 장점이 있다.&lt;/p&gt;
&lt;p&gt;도메인의 사용처를 &lt;code&gt;alsoKnownAs&lt;/code&gt;를 채우는 데만 쓰는 게 가능하다. PLC Directory가 망하지 않는 이상, 도메인이 털려도 PLC Directory는 털리지 않으니 원래 있던 recovery 키로 &lt;code&gt;alsoKnownAs&lt;/code&gt;를 수정하면 그만이다.
이 장점 덕분에 절대 다수의 유저들은 &lt;code&gt;did:plc&lt;/code&gt;를 사용한다.&lt;/p&gt;
&lt;h2&gt;DID의 검증&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://pdsls.dev/at://did:plc:qjua73d5eq537nio2sucdaj3&quot;&gt;PDSls 서비스에서 DID document&lt;/a&gt;를 보기 쉽게 확인할 수 있다. 여기서 Identity 탭의 Aliases 항목을 보자.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;이는 DID document의 &lt;code&gt;alsoKnownAs&lt;/code&gt;를 알려주는 곳이다. DNS (TXT record) 항목에서 &lt;code&gt;did:plc:qjua73d5eq537nio2sucdaj3&lt;/code&gt;가 적혀임을 알 수 있다.
DID document에서 &lt;code&gt;did:plc:qjua...&lt;/code&gt;가 &lt;code&gt;euroka.moe&lt;/code&gt;를 통제한다고 주장한다. 주장일 뿐이고, 인증되지 않았다. 이제 &lt;code&gt;euroka.moe&lt;/code&gt;가 &lt;code&gt;did:plc:qjua...&lt;/code&gt;를 통제한다고 주장하면 상호 통제 상태가 되고, 즉 같은 사람에게 제어받는다 생각할 수 있다.&lt;/p&gt;
&lt;p&gt;핸들의 &lt;code&gt;${핸들}/.well-known/atproto-did&lt;/code&gt; 파일을 확인해서 검증할 수도 있지만, 이는 예시로 쓸 사용자가 없어 생략한다.&lt;/p&gt;
</content:encoded></item><item><title>서버 배포를 쌀먹하기 w. Hono</title><link>https://blog.euroka.moe/posts/deployment/</link><guid isPermaLink="true">https://blog.euroka.moe/posts/deployment/</guid><pubDate>Sat, 07 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;돈벌기&lt;/h1&gt;
&lt;p&gt;&amp;lt;img src=&quot;./images/194a891a978577680.png&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;돈이 없다. 이것은 학생의 숙명이다. 프리티어를 떠도는 노마드의 삶이다.
그런데 코딩을 하면 배포할 일이 생긴다. 당연한 거 아닌가. 배포를 그럼 git clone하라고 할 수도 없지 않나.&lt;/p&gt;
&lt;h1&gt;FaaS/서버리스&lt;/h1&gt;
&lt;p&gt;서버리스의 장점은 그것이다. 24/7이 필요하긴 한데, 굳이 막 항상 사람이 들어오는 건 아닌 사이트 많지 않나? 그런 상황이 많다.
서버리스는 그 상황에 딱 맞는다. 트래픽 없다? 서버 내릴게. 서버 내려? 돈 안뺄게.&lt;/p&gt;
&lt;h2&gt;Azure Functions&lt;/h2&gt;
&lt;p&gt;Azure Functions는 마이크로소프트의 서버리스 플랫폼이다.&lt;/p&gt;
&lt;p&gt;장점:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;언어 독립적이다, 안 되면 커스텀 핸들러로 어떻게든 된다&lt;/li&gt;
&lt;li&gt;SLA가 있다(무료티어 포함)&lt;/li&gt;
&lt;li&gt;무료 티어도 있고 학생 크레딧을 쓸 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;단점:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;하드캡이 없다. 카드 넣어야 한다&lt;/li&gt;
&lt;li&gt;콜드 스타트가 좀 걸린다&lt;/li&gt;
&lt;li&gt;저장공간은 또 다른 서비스 써야 한다&lt;/li&gt;
&lt;li&gt;&lt;s&gt;꽤 고립적이다&lt;/s&gt; &lt;a href=&quot;#hono&quot;&gt;Hono&lt;/a&gt;가 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cloudflare Workers&lt;/h2&gt;
&lt;p&gt;Cloudflare Workers는 JS를 지원하는 FaaS이다.&lt;/p&gt;
&lt;p&gt;장점:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;빠른 콜드 스타트(0ms!!!!)&lt;/li&gt;
&lt;li&gt;무료티어 넘어가면 청구 없이 터진다(Paid 플랜 업그레이드하지 않으면)&lt;/li&gt;
&lt;li&gt;CI/CD를 CF에서 제공한다(=Github Action 요금 낼 필요 없다, 워크플로우 짤 필요 없다)&lt;/li&gt;
&lt;li&gt;분당 1000회 무료 티어&lt;/li&gt;
&lt;li&gt;다른 WinterTC 계열 서비스 대비 더 넉넉하다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;단점:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JS와 WASM 컴파일을 지원하는 일부 언어만 가능하다&lt;/li&gt;
&lt;li&gt;Github Action은 어짜피 퍼블릭레포 무제한 무료라 굳이...?&lt;/li&gt;
&lt;li&gt;런타임은 Node.JS와 거리가 멀다, DOM 없다&lt;/li&gt;
&lt;li&gt;CPU 타임이 제한적이다(무료플랜 10ms/콜)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Deno Deploy&lt;/h2&gt;
&lt;p&gt;Deno Deploy는 Cloudflare Workers와 유사한 FaaS 호스팅 서비스다.&lt;/p&gt;
&lt;p&gt;장점:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cloudflare Workers 대비 넉넉한 CPU 타임(15h/월)&lt;/li&gt;
&lt;li&gt;빠른 콜드 스타트&lt;/li&gt;
&lt;li&gt;셋업하기 쉽다(&lt;code&gt;import { Hono } from &quot;jsr:hono&quot;&lt;/code&gt;, TypeScript OOTB 지원 등)&lt;/li&gt;
&lt;li&gt;제일 JS스럽고, 배워야 할 자체 개념이 적다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;단점:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JS/TS만 지원한다&lt;/li&gt;
&lt;li&gt;카드 등록이 필요하다(업그레이드하기 전까진 billing X)&lt;/li&gt;
&lt;li&gt;Cloudflare Workers 대비 물리적 인프라가 떨어진다&lt;/li&gt;
&lt;li&gt;다들 Cloudflare 계정은 있지만 Deno Deploy는 없는 경우도 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Hono&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;신&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Hono는 각종 FaaS 프로바이더를 위한 프레임워크다.
지원하는 실행 환경은...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Deno(Deno Deploy 포함)&lt;/li&gt;
&lt;li&gt;Bun&lt;/li&gt;
&lt;li&gt;WebAssembly&lt;/li&gt;
&lt;li&gt;Service Worker&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이러하다. 또 호스팅은 이 플랫폼들을 지원한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cloudflare Workers, Cloudflare Pages&lt;/li&gt;
&lt;li&gt;Fastly Compute&lt;/li&gt;
&lt;li&gt;Vercel, Netlify&lt;/li&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;AWS Lambda, Lambda@Edge&lt;/li&gt;
&lt;li&gt;Azure Functions&lt;/li&gt;
&lt;li&gt;Google Cloud Run&lt;/li&gt;
&lt;li&gt;Supabase Functions&lt;/li&gt;
&lt;li&gt;Ali Function Compute&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 무슨 개얼탱없는 라인업이란 말인가. 당장 써야지.
원래 FaaS 서비스들은 꽤 벤더 종속적이다.
벤더에서 제공한 API를 쓰게 되는데, 이러면 다른 곳으로 마이그레이션하기 상당히 어렵다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Cloudflare Workers, ES Modules 문법
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    const name = url.searchParams.get(&apos;name&apos;);

    if (name) {
      return new Response(`Hello, ${name}! Welcome to Cloudflare Workers.`, {
        status: 200,
        headers: {
          &apos;Content-Type&apos;: &apos;text/plain; charset=utf-8&apos;,
        },
      });
    } else {
      return new Response(&apos;Hello World! This is Cloudflare Workers.&apos;, {
        status: 200,
        headers: {
          &apos;Content-Type&apos;: &apos;text/plain; charset=utf-8&apos;,
        },
      });
    }
  },
};
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// Azure Functions
export async function serve(context, req) {
  context.log(&apos;HTTP trigger function processed a request.&apos;);

  const name = req.query.name || (req.body &amp;amp;&amp;amp; req.body.name);

  if (name) {
    context.res = {
      status: 200,
      body: `Hello, ${name}! Welcome to Azure Functions.`
    };
  } else {
    context.res = {
      status: 200,
      body: &apos;Hello World! This is Azure Functions.&apos;
    };
  }
};
export default serve;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;네이티브 API를 쓰면 벌써 코드가 다르다.
CF Workers는 함수를 객체에 담아 &lt;code&gt;export default&lt;/code&gt;하고, 그 함수는 Response 객체를 리턴한다.
하지면 Azure Functions는 함수가 &lt;code&gt;context.res&lt;/code&gt;를 수정한다.&lt;/p&gt;
&lt;p&gt;그런데 그때, Hono가 등장한다...&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Hono } from &apos;hono&apos;;

type Env = {
  Bindings: Record&amp;lt;string, unknown&amp;gt;;
};

const app = new Hono&amp;lt;Env&amp;gt;();

// POST 요청 처리 예제
app.post(&apos;/api/hello&apos;, async (c) =&amp;gt; {
  const body = await c.req.json&amp;lt;{ name?: string }&amp;gt;();
  const name = body.name || &apos;World&apos;;

  return c.json({
    message: `Hello, ${name}!`,
    method: &apos;POST&apos;,
    framework: &apos;Hono&apos;,
  });
});

export default app;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이거, 어디선가 본 패턴이지 않은가?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import express, { Request, Response } from &apos;express&apos;;

const app = express();

app.use(express.json());

app.post(&apos;/api/hello&apos;, (req: Request, res: Response) =&amp;gt; {
  const body = req.body as { name?: string };
  const name = body.name || &apos;World&apos;;

  res.json({
    message: `Hello, ${name}!`,
    method: &apos;POST&apos;,
    framework: &apos;Express&apos;,
  });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () =&amp;gt; {
  console.log(`Server is running on port ${PORT}`);
});

export default app;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Express.js와 매우 유사하다. 선언적이고, 자유분방하다.
게다가 타입스크립트를 염두하고 만들어졌기 때문에,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;//...
const app=new Hono()
    .post(&quot;/post&quot;, ...)
    .get(&quot;/get&quot;, ...);
export default app;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이와 같은 방식으로 메서드 체인을 걸면, app의 타입 자체에 라우트 정보가 작성된다.
이는 RPC나 &lt;a href=&quot;https://hono.dev/docs/helpers/testing&quot;&gt;테스팅&lt;/a&gt; 시 매우 유용하다.&lt;/p&gt;
&lt;p&gt;개인 사용을 위해 &lt;a href=&quot;https://github.com/templecon/template-hono&quot;&gt;Hono용 템플릿&lt;/a&gt;을 작성해두었다.&lt;/p&gt;
</content:encoded></item><item><title>안녕 세계</title><link>https://blog.euroka.moe/posts/init/</link><guid isPermaLink="true">https://blog.euroka.moe/posts/init/</guid><description>첫글!!!</description><pubDate>Sat, 21 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;안녕! 👋 오늘부터 블로그를 시작합니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://media4.giphy.com/media/v1.Y2lkPTc5MGI3NjExZnhydmcxdTBjbGdkYm5oczE1ZXNtZzBqMWJkcGszM29zMndicTVhNSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/80j4Bo8di25QscQNum/giphy.gif&quot; alt=&quot;셰럼 글쓰기&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>작은 스크립트 파일은 Deno를 쓰는 것에 대하여</title><link>https://blog.euroka.moe/posts/why-deno/</link><guid isPermaLink="true">https://blog.euroka.moe/posts/why-deno/</guid><pubDate>Sat, 21 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Node.js에서의 타입스크립트&lt;/h2&gt;
&lt;p&gt;Node.js에서 타입스크립트를 쓰려면, 3가지 방법이 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;타입스크립트용 REPL을 사용한다.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tsx&lt;/code&gt; 패키지를 설치해야 한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tsx&lt;/code&gt; 명령어로 타입스크립트 코드를 실행시킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;타입스크립트 프로젝트를 생성한다.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tsconfig.json&lt;/code&gt; 파일을 만들어야 한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;esbuild&lt;/code&gt;나 &lt;code&gt;tsc&lt;/code&gt;로 타입스크립트를 자바스크립트로 컴파일해야 한다.&lt;/li&gt;
&lt;li&gt;그렇기에, package.json과 node_modules도 필요하다.&lt;/li&gt;
&lt;li&gt;컴파일된 자바스크립트 파일을 실행해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Node.js를 믿는다.
&lt;ul&gt;
&lt;li&gt;일단 타입스크립트 파일을 실행시킨다.&lt;/li&gt;
&lt;li&gt;Node.js의 &lt;code&gt;--strip-types&lt;/code&gt;를 믿고 실행한다.&lt;/li&gt;
&lt;li&gt;strip 가능한 코드가 아니라면서, 에러가 난다.
&lt;img src=&quot;image.png&quot; alt=&quot;alt text&quot; /&gt;&lt;/li&gt;
&lt;li&gt;이제 &lt;code&gt;--experimental-transform-types&lt;/code&gt;를 쓴다.&lt;/li&gt;
&lt;li&gt;매번 플래그 넘겨주려니까 귀찮다.&lt;/li&gt;
&lt;li&gt;결국 tsx를 설치한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;lt;img src=&quot;./images/200.gif&quot; alt=&quot;GIF&quot; /&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;gt; 서기관 셰럼, 이건 좀 너무한다고 생각함.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;그럼 타입스크립트 왜씀?&lt;/h2&gt;
&lt;p&gt;타입스크립트는 자바스크립트보다 빌드 타임에 많은 정보를 알게 된다.
이곳에서 오는 크나큰 장점이 있다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;자동완성&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;JS는 object의 프로퍼티가 무엇인지 알 수 없다. 그래서 자동완성이 안된다.&lt;/p&gt;
&lt;p&gt;TS는 정보를 .ts 파일이나 .d.ts 파일에 모두 담아놓는다. number에는 toFixed가 있고, string에는 toUpperCase가 있다는 것을 알고 있다. toUpperCase는 파라미터를 아무것도 받지 않은 &lt;code&gt;()=&amp;gt;string&lt;/code&gt; 타입의 함수임을 lib.d.ts에 적어놓는다.&lt;/p&gt;
&lt;p&gt;JS는 이상한 기교가 있다. 빈 배열과 느낌표, 더하기, 이상한 기호 몇 개로 모든 코드를 만들 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[]+[] // &quot;&quot;
[]+{} // &quot;[object Object]&quot;
{}+[] // 0
{}+{} // NaN
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 무슨 쓰레기 언어란 말인가. 타입스크립트 안 쓸 이유가 없지 않나?&lt;/p&gt;
&lt;p&gt;&amp;lt;img src=&quot;./images/giphy.webp&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;gt; 정체성의 유령도 한물 두물 세물 간 자바스크립트를 버리고 타입스크립트에 어울리는...&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;빨간약&lt;/h2&gt;
&lt;p&gt;하지만 타입스크립트는 딱 하나의 문제점이 있다. 결국 실행을 못 한다.&lt;/p&gt;
&lt;p&gt;&amp;lt;img src=&quot;./images/19af9216e4c133c46.png&quot; width=&quot;200&quot; /&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;gt; 으에엥 타입스크립트 네르지 마세요&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;그러면 타입스크립트 코드를 자바스크립트 코드로 변환하고, 실행하고, 그걸 반복하면 되지 않을까?
가능하다. Node.js의 &lt;code&gt;--strip-types&lt;/code&gt;가 비슷하게 한다.
하지만 이는 &lt;code&gt;const enum&lt;/code&gt;과 같은 일부 기능을 지원하지 않는다. &lt;code&gt;--experimental-transform-types&lt;/code&gt; 플래그를 써야 한다. 하지만 이름에서 알 수 있듯이 이는 실험적이다. 언제 터져도 이상하지 않다는 것이다.&lt;/p&gt;
&lt;h2&gt;그렇게 엄청 간단하지는 않은 스크립트&lt;/h2&gt;
&lt;p&gt;예시로, &lt;code&gt;hello.ts&lt;/code&gt;라는 파일을 만들어보자.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;console.log(&quot;Hello, world!&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이는 충분히 간단하다. tsx로도 실행할 수 있다.
하지만, 조금 복잡한 스크립트는 어떨까?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// openai.ts
const prompt=&apos;&quot;크아앙&quot;\n투명드래곤이 울부짖었다.\n\n이 다음 소설의 내용을 이어서 써줘.&apos;;

const response = await fetch(&quot;https://api.openai.com/v1/chat/completions&quot;, {
  method: &quot;POST&quot;,
  headers: {
    &quot;Content-Type&quot;: &quot;application/json&quot;,
    &quot;Authorization&quot;: `Bearer ${process.env.OPENAI_API_KEY}`,
  },
  body: JSON.stringify({
    model: &quot;gpt-5-mini&quot;,
    messages: [{ role: &quot;user&quot;, content: prompt }],
  }),
});
const data = await response.json();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;img src=&quot;./images/3_EC_BB_B7.gif&quot; width=&quot;400&quot; /&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;gt; 한 동인지 작가의 흑역사를 드러내고 있다.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;조금 복잡해진다. 이제 스트리밍도 추가해볼까?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// openai.ts
const prompt=&apos;&quot;크아앙&quot;\n투명드래곤이 울부짖었다.\n\n이 다음 소설의 내용을 이어서 써줘.&apos;;
const response = await fetch(&quot;https://api.openai.com/v1/chat/completions&quot;, {
  method: &quot;POST&quot;,
  headers: {
    &quot;Content-Type&quot;: &quot;application/json&quot;,
    &quot;Authorization&quot;: `Bearer ${process.env.OPENAI_API_KEY}`,
  },
  body: JSON.stringify({
    model: &quot;gpt-5-mini&quot;,
    messages: [{ role: &quot;user&quot;, content: prompt }],
    stream: true,
  }),
});
const reader = response.body.getReader();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  const chunk = new TextDecoder().decode(value);
  console.log(chunk);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;img src=&quot;./images/i-SrNCqaDPPKDhBa2nAg_8y4z6guRNb67uAE9D09hF9ZAmN5ayhkvd1m7cl_99HOpZpi7GgOa3h2mEkMWrvRaq_VvWJG-7oAmbHs30mAfGDKtIBPhXTpTI5tGzI6l2teZ_OGL95hKk_YGzVtTiKZ0w.webp&quot; width=&quot;400&quot; /&amp;gt;&lt;/p&gt;
&lt;p&gt;물론 여기서 저 청크 하나하나도 JSON이니까, JSON.parse를 해야 한다. 메세지 델타들에 대해 조금씩 출력하고, 메세지 끝에 도달했는지 확인하는 로직도 필요하다.&lt;/p&gt;
&lt;h2&gt;Deno를 쓰세요&lt;/h2&gt;
&lt;p&gt;tsx는 Node.js다. 라이브러리를 설치하려면, node_modules에 넣어야 한다. 방법은? &lt;code&gt;pnpm add&lt;/code&gt;와 package.json 관리, 그리고 기타 귀찮은 파일 관리를 해야 한다.&lt;/p&gt;
&lt;p&gt;Deno는 Deno다. 라이브러리를 사용하려면,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import OpenAI from &apos;jsr:@openai/openai&apos;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 얼마나 간결한가. Deno로 위 예시를 다시 짜 보자.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import OpenAI from &quot;jsr:@openai/openai&quot;;

const client = new OpenAI();

const stream = await client.responses.create({
  model: &quot;gpt-5-mini&quot;,
  input: &apos;&quot;크아앙&quot;\n투명드래곤이 울부짖었다.\n\n이 다음 소설의 내용을 이어서 써줘.&apos;,
  stream: true,
});

for await (const event of stream) {
  console.log(event);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;타입스크립트? Deno는 된다.&lt;/p&gt;
&lt;p&gt;&amp;lt;img src=&quot;./images/198b318a37d4da809.jpg&quot; width=&quot;400&quot; /&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;gt; 긴긴-팔다리의 출몰에 정신을 잃은 셰럼&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title>Markdown Extended Features</title><link>https://blog.euroka.moe/posts/markdown-extended/</link><guid isPermaLink="true">https://blog.euroka.moe/posts/markdown-extended/</guid><description>Read more about Markdown features in Fuwari</description><pubDate>Wed, 01 May 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;GitHub Repository Cards&lt;/h2&gt;
&lt;p&gt;You can add dynamic cards that link to GitHub repositories, on page load, the repository information is pulled from the GitHub API.&lt;/p&gt;
&lt;p&gt;::github{repo=&quot;Fabrizz/MMM-OnSpotify&quot;}&lt;/p&gt;
&lt;p&gt;Create a GitHub repository card with the code &lt;code&gt;::github{repo=&quot;&amp;lt;owner&amp;gt;/&amp;lt;repo&amp;gt;&quot;}&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;::github{repo=&quot;saicaca/fuwari&quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Admonitions&lt;/h2&gt;
&lt;p&gt;Following types of admonitions are supported: &lt;code&gt;note&lt;/code&gt; &lt;code&gt;tip&lt;/code&gt; &lt;code&gt;important&lt;/code&gt; &lt;code&gt;warning&lt;/code&gt; &lt;code&gt;caution&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;:::note
Highlights information that users should take into account, even when skimming.
:::&lt;/p&gt;
&lt;p&gt;:::tip
Optional information to help a user be more successful.
:::&lt;/p&gt;
&lt;p&gt;:::important
Crucial information necessary for users to succeed.
:::&lt;/p&gt;
&lt;p&gt;:::warning
Critical content demanding immediate user attention due to potential risks.
:::&lt;/p&gt;
&lt;p&gt;:::caution
Negative potential consequences of an action.
:::&lt;/p&gt;
&lt;h3&gt;Basic Syntax&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;:::note
Highlights information that users should take into account, even when skimming.
:::

:::tip
Optional information to help a user be more successful.
:::
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Custom Titles&lt;/h3&gt;
&lt;p&gt;The title of the admonition can be customized.&lt;/p&gt;
&lt;p&gt;:::note[MY CUSTOM TITLE]
This is a note with a custom title.
:::&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:::note[MY CUSTOM TITLE]
This is a note with a custom title.
:::
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;GitHub Syntax&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;[!TIP]
&lt;a href=&quot;https://github.com/orgs/community/discussions/16925&quot;&gt;The GitHub syntax&lt;/a&gt; is also supported.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; [!NOTE]
&amp;gt; The GitHub syntax is also supported.

&amp;gt; [!TIP]
&amp;gt; The GitHub syntax is also supported.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Spoiler&lt;/h3&gt;
&lt;p&gt;You can add spoilers to your text. The text also supports &lt;strong&gt;Markdown&lt;/strong&gt; syntax.&lt;/p&gt;
&lt;p&gt;The content :spoiler[is hidden &lt;strong&gt;ayyy&lt;/strong&gt;]!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;The content :spoiler[is hidden **ayyy**]!

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Expressive Code Example</title><link>https://blog.euroka.moe/posts/expressive-code/</link><guid isPermaLink="true">https://blog.euroka.moe/posts/expressive-code/</guid><description>How code blocks look in Markdown using Expressive Code.</description><pubDate>Wed, 10 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Here, we&apos;ll explore how code blocks look using &lt;a href=&quot;https://expressive-code.com/&quot;&gt;Expressive Code&lt;/a&gt;. The provided examples are based on the official documentation, which you can refer to for further details.&lt;/p&gt;
&lt;h2&gt;Expressive Code&lt;/h2&gt;
&lt;h3&gt;Syntax Highlighting&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/key-features/syntax-highlighting/&quot;&gt;Syntax Highlighting&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Regular syntax highlighting&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;This code is syntax highlighted!&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Rendering ANSI escape sequences&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;ANSI colors:
- Regular: [31mRed[0m [32mGreen[0m [33mYellow[0m [34mBlue[0m [35mMagenta[0m [36mCyan[0m
- Bold:    [1;31mRed[0m [1;32mGreen[0m [1;33mYellow[0m [1;34mBlue[0m [1;35mMagenta[0m [1;36mCyan[0m
- Dimmed:  [2;31mRed[0m [2;32mGreen[0m [2;33mYellow[0m [2;34mBlue[0m [2;35mMagenta[0m [2;36mCyan[0m

256 colors (showing colors 160-177):
[38;5;160m160 [38;5;161m161 [38;5;162m162 [38;5;163m163 [38;5;164m164 [38;5;165m165[0m
[38;5;166m166 [38;5;167m167 [38;5;168m168 [38;5;169m169 [38;5;170m170 [38;5;171m171[0m
[38;5;172m172 [38;5;173m173 [38;5;174m174 [38;5;175m175 [38;5;176m176 [38;5;177m177[0m

Full RGB colors:
[38;2;34;139;34mForestGreen - RGB(34, 139, 34)[0m

Text formatting: [1mBold[0m [2mDimmed[0m [3mItalic[0m [4mUnderline[0m
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Editor &amp;amp; Terminal Frames&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/key-features/frames/&quot;&gt;Editor &amp;amp; Terminal Frames&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Code editor frames&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;Title attribute example&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- src/content/index.html --&amp;gt;
&amp;lt;div&amp;gt;File name comment example&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Terminal frames&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;This terminal frame has no title&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;Write-Output &quot;This one has a title!&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Overriding frame types&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;Look ma, no frame!&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;# Without overriding, this would be a terminal frame
function Watch-Tail { Get-Content -Tail 20 -Wait $args }
New-Alias tail Watch-Tail
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Text &amp;amp; Line Markers&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/key-features/text-markers/&quot;&gt;Text &amp;amp; Line Markers&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Marking full lines &amp;amp; line ranges&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Line 1 - targeted by line number
// Line 2
// Line 3
// Line 4 - targeted by line number
// Line 5
// Line 6
// Line 7 - targeted by range &quot;7-8&quot;
// Line 8 - targeted by range &quot;7-8&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Selecting line marker types (mark, ins, del)&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;function demo() {
  console.log(&apos;this line is marked as deleted&apos;)
  // This line and the next one are marked as inserted
  console.log(&apos;this is the second inserted line&apos;)

  return &apos;this line uses the neutral default marker type&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Adding labels to line markers&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// labeled-line-markers.jsx
&amp;lt;button
  role=&quot;button&quot;
  {...props}
  value={value}
  className={buttonClassName}
  disabled={disabled}
  active={active}
&amp;gt;
  {children &amp;amp;&amp;amp;
    !active &amp;amp;&amp;amp;
    (typeof children === &apos;string&apos; ? &amp;lt;span&amp;gt;{children}&amp;lt;/span&amp;gt; : children)}
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Adding long labels on their own lines&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// labeled-line-markers.jsx
&amp;lt;button
  role=&quot;button&quot;
  {...props}

  value={value}
  className={buttonClassName}

  disabled={disabled}
  active={active}
&amp;gt;

  {children &amp;amp;&amp;amp;
    !active &amp;amp;&amp;amp;
    (typeof children === &apos;string&apos; ? &amp;lt;span&amp;gt;{children}&amp;lt;/span&amp;gt; : children)}
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Using diff-like syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;+this line will be marked as inserted
-this line will be marked as deleted
this is a regular line
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+this is an actual diff file
-all contents will remain unmodified
 no whitespace will be removed either
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Combining syntax highlighting with diff-like syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;  function thisIsJavaScript() {
    // This entire block gets highlighted as JavaScript,
    // and we can still add diff markers to it!
-   console.log(&apos;Old code to be removed&apos;)
+   console.log(&apos;New and shiny code!&apos;)
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Marking individual text inside lines&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;function demo() {
  // Mark any given text inside lines
  return &apos;Multiple matches of the given text are supported&apos;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Regular expressions&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;The words yes and yep will be marked.&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Escaping forward slashes&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;Test&quot; &amp;gt; /home/test.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Selecting inline marker types (mark, ins, del)&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;function demo() {
  console.log(&apos;These are inserted and deleted marker types&apos;);
  // The return statement uses the default marker type
  return true;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Word Wrap&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/key-features/word-wrap/&quot;&gt;Word Wrap&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Configuring word wrap per block&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Example with wrap
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;// Example with wrap=false
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Configuring indentation of wrapped lines&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Example with preserveIndent (enabled by default)
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;// Example with preserveIndent=false
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Collapsible Sections&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/plugins/collapsible-sections/&quot;&gt;Collapsible Sections&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// All this boilerplate setup code will be collapsed
import { someBoilerplateEngine } from &apos;@example/some-boilerplate&apos;
import { evenMoreBoilerplate } from &apos;@example/even-more-boilerplate&apos;

const engine = someBoilerplateEngine(evenMoreBoilerplate())

// This part of the code will be visible by default
engine.doSomething(1, 2, 3, calcFn)

function calcFn() {
  // You can have multiple collapsed sections
  const a = 1
  const b = 2
  const c = a + b

  // This will remain visible
  console.log(`Calculation result: ${a} + ${b} = ${c}`)
  return c
}

// All this code until the end of the block will be collapsed again
engine.closeConnection()
engine.freeMemory()
engine.shutdown({ reason: &apos;End of example boilerplate code&apos; })
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Line Numbers&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/plugins/line-numbers/&quot;&gt;Line Numbers&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Displaying line numbers per block&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// This code block will show line numbers
console.log(&apos;Greetings from line 2!&apos;)
console.log(&apos;I am on line 3&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;// Line numbers are disabled for this block
console.log(&apos;Hello?&apos;)
console.log(&apos;Sorry, do you know what line I am on?&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Changing the starting line number&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;Greetings from line 5!&apos;)
console.log(&apos;I am on line 6&apos;)
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Simple Guides for Fuwari</title><link>https://blog.euroka.moe/posts/guide/</link><guid isPermaLink="true">https://blog.euroka.moe/posts/guide/</guid><description>How to use this blog template.</description><pubDate>Mon, 01 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;Cover image source: &lt;a href=&quot;https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/208fc754-890d-4adb-9753-2c963332675d/width=2048/01651-1456859105-(colour_1.5),girl,_Blue,yellow,green,cyan,purple,red,pink,_best,8k,UHD,masterpiece,male%20focus,%201boy,gloves,%20ponytail,%20long%20hair,.jpeg&quot;&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This blog template is built with &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;. For the things that are not mentioned in this guide, you may find the answers in the &lt;a href=&quot;https://docs.astro.build/&quot;&gt;Astro Docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Front-matter of Posts&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;---
title: My First Blog Post
published: 2023-09-09
description: This is the first post of my new Astro blog.
image: ./cover.jpg
tags: [Foo, Bar]
category: Front-end
draft: false
---
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The title of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;published&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The date the post was published.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A short description of the post. Displayed on index page.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;image&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The cover image path of the post.&amp;lt;br/&amp;gt;1. Start with &lt;code&gt;http://&lt;/code&gt; or &lt;code&gt;https://&lt;/code&gt;: Use web image&amp;lt;br/&amp;gt;2. Start with &lt;code&gt;/&lt;/code&gt;: For image in &lt;code&gt;public&lt;/code&gt; dir&amp;lt;br/&amp;gt;3. With none of the prefixes: Relative to the markdown file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The tags of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;category&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The category of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;draft&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;If this post is still a draft, which won&apos;t be displayed.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Where to Place the Post Files&lt;/h2&gt;
&lt;p&gt;Your post files should be placed in &lt;code&gt;src/content/posts/&lt;/code&gt; directory. You can also create sub-directories to better organize your posts and assets.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/content/posts/
├── post-1.md
└── post-2/
    ├── cover.png
    └── index.md
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Markdown Example</title><link>https://blog.euroka.moe/posts/markdown/</link><guid isPermaLink="true">https://blog.euroka.moe/posts/markdown/</guid><description>A simple example of a Markdown blog post.</description><pubDate>Sun, 01 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;An h1 header&lt;/h1&gt;
&lt;p&gt;Paragraphs are separated by a blank line.&lt;/p&gt;
&lt;p&gt;2nd paragraph. &lt;em&gt;Italic&lt;/em&gt;, &lt;strong&gt;bold&lt;/strong&gt;, and &lt;code&gt;monospace&lt;/code&gt;. Itemized lists
look like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this one&lt;/li&gt;
&lt;li&gt;that one&lt;/li&gt;
&lt;li&gt;the other one&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that --- not considering the asterisk --- the actual text
content starts at 4-columns in.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Block quotes are
written like so.&lt;/p&gt;
&lt;p&gt;They can span multiple paragraphs,
if you like.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., &quot;it&apos;s all
in chapters 12--14&quot;). Three dots ... will be converted to an ellipsis.
Unicode is supported. ☺&lt;/p&gt;
&lt;h2&gt;An h2 header&lt;/h2&gt;
&lt;p&gt;Here&apos;s a numbered list:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;first item&lt;/li&gt;
&lt;li&gt;second item&lt;/li&gt;
&lt;li&gt;third item&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note again how the actual text starts at 4 columns in (4 characters
from the left side). Here&apos;s a code sample:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Let me re-iterate ...
for i in 1 .. 10 { do-something(i) }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you probably guessed, indented 4 spaces. By the way, instead of
indenting the block, you can use delimited blocks, if you like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;define foobar() {
    print &quot;Welcome to flavor country!&quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(which makes copying &amp;amp; pasting easier). You can optionally mark the
delimited block for Pandoc to syntax highlight it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import time
# Quick, count to ten!
for i in range(10):
    # (but not *too* quick)
    time.sleep(0.5)
    print i
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;An h3 header&lt;/h3&gt;
&lt;p&gt;Now a nested list:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First, get these ingredients:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;carrots&lt;/li&gt;
&lt;li&gt;celery&lt;/li&gt;
&lt;li&gt;lentils&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Boil some water.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dump everything in the pot and follow
this algorithm:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; find wooden spoon
 uncover pot
 stir
 cover pot
 balance wooden spoon precariously on pot handle
 wait 10 minutes
 goto first step (or shut off burner when done)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Do not bump wooden spoon or it will fall.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Notice again how text always lines up on 4-space indents (including
that last line which continues item 3 above).&lt;/p&gt;
&lt;p&gt;Here&apos;s a link to &lt;a href=&quot;http://foo.bar&quot;&gt;a website&lt;/a&gt;, to a &lt;a href=&quot;local-doc.html&quot;&gt;local
doc&lt;/a&gt;, and to a &lt;a href=&quot;#an-h2-header&quot;&gt;section heading in the current
doc&lt;/a&gt;. Here&apos;s a footnote [^1].&lt;/p&gt;
&lt;p&gt;[^1]: Footnote text goes here.&lt;/p&gt;
&lt;p&gt;Tables can look like this:&lt;/p&gt;
&lt;p&gt;size material color&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;9 leather brown
10 hemp canvas natural
11 glass transparent&lt;/p&gt;
&lt;p&gt;Table: Shoes, their sizes, and what they&apos;re made of&lt;/p&gt;
&lt;p&gt;(The above is the caption for the table.) Pandoc also supports
multi-line tables:&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;keyword text&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;red Sunsets, apples, and
other red or reddish
things.&lt;/p&gt;
&lt;p&gt;green Leaves, grass, frogs
and other things it&apos;s
not easy being.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;A horizontal rule follows.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Here&apos;s a definition list:&lt;/p&gt;
&lt;p&gt;apples
: Good for making applesauce.
oranges
: Citrus!
tomatoes
: There&apos;s no &quot;e&quot; in tomatoe.&lt;/p&gt;
&lt;p&gt;Again, text is indented 4 spaces. (Put a blank line between each
term/definition pair to spread things out more.)&lt;/p&gt;
&lt;p&gt;Here&apos;s a &quot;line block&quot;:&lt;/p&gt;
&lt;p&gt;| Line one
| Line too
| Line tree&lt;/p&gt;
&lt;p&gt;and images can be specified like so:&lt;/p&gt;
&lt;p&gt;Inline math equations go in like so: $\omega = d\phi / dt$. Display
math should get its own line and be put in in double-dollarsigns:&lt;/p&gt;
&lt;p&gt;$$I = \int \rho R^{2} dV$$&lt;/p&gt;
&lt;p&gt;$$
\begin{equation*}
\pi
=3.1415926535
;8979323846;2643383279;5028841971;6939937510;5820974944
;5923078164;0628620899;8628034825;3421170679;\ldots
\end{equation*}
$$&lt;/p&gt;
&lt;p&gt;And note that you can backslash-escape any punctuation characters
which you wish to be displayed literally, ex.: `foo`, *bar*, etc.&lt;/p&gt;
</content:encoded></item><item><title>Include Video in the Posts</title><link>https://blog.euroka.moe/posts/video/</link><guid isPermaLink="true">https://blog.euroka.moe/posts/video/</guid><description>This post demonstrates how to include embedded video in a blog post.</description><pubDate>Tue, 01 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Just copy the embed code from YouTube or other platforms, and paste it in the markdown file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Include Video in the Post
published: 2023-10-19
// ...
---

&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;https://www.youtube.com/embed/5gIf0_xpFPI?si=N1WTorLKL0uwLsU_&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;YouTube&lt;/h2&gt;
&lt;p&gt;&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;https://www.youtube.com/embed/5gIf0_xpFPI?si=N1WTorLKL0uwLsU_&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;h2&gt;Bilibili&lt;/h2&gt;
&lt;p&gt;&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;//player.bilibili.com/player.html?bvid=BV1fK4y1s7Qf&amp;amp;p=1&quot; scrolling=&quot;no&quot; border=&quot;0&quot; frameborder=&quot;no&quot; framespacing=&quot;0&quot; allowfullscreen=&quot;true&quot;&amp;gt; &amp;lt;/iframe&amp;gt;&lt;/p&gt;
</content:encoded></item></channel></rss>