@hackersheet/next-document-content-components 0.1.0-alpha.2 → 0.1.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/code-block/code-block-copy-button.d.ts +13 -2
- package/dist/cjs/components/code-block/code-block-copy-button.js +2 -2
- package/dist/cjs/components/code-block/code-block-icon.d.ts +38 -4
- package/dist/cjs/components/code-block/code-block-icon.js +12 -0
- package/dist/cjs/components/code-block/code-block.d.ts +1 -1
- package/dist/cjs/components/code-block/code-block.js +3 -9
- package/dist/cjs/components/code-block/directory-tree-item.d.ts +15 -0
- package/dist/cjs/components/code-block/directory-tree-item.js +38 -0
- package/dist/cjs/components/code-block/directory-tree.d.ts +13 -0
- package/dist/cjs/components/code-block/{code-block-kifu.js → directory-tree.js} +12 -35
- package/dist/cjs/components/code-block/parse-tree-output.d.ts +26 -0
- package/dist/cjs/components/code-block/parse-tree-output.js +111 -0
- package/dist/cjs/components/code-block/shiki.js +25 -7
- package/dist/cjs/components/gist/gist.d.ts +6 -0
- package/dist/cjs/components/{index.js → gist/gist.js} +26 -27
- package/dist/cjs/components/heading/heading.d.ts +6 -0
- package/dist/cjs/components/{kifu-to/kifu-to.js → heading/heading.js} +7 -9
- package/dist/cjs/components/image/image.js +1 -2
- package/dist/cjs/components/link/link.js +1 -1
- package/dist/cjs/components/link-card/link-card.js +1 -2
- package/dist/cjs/components/mermaid/mermaid.d.ts +6 -0
- package/dist/cjs/components/{code-block/code-block-mermaid.js → mermaid/mermaid.js} +9 -8
- package/dist/cjs/components/youtube/youtube.js +1 -1
- package/dist/cjs/index.d.ts +4 -1
- package/dist/cjs/index.js +48 -5
- package/dist/esm/components/code-block/code-block-copy-button.d.mts +13 -2
- package/dist/esm/components/code-block/code-block-copy-button.mjs +2 -2
- package/dist/esm/components/code-block/code-block-icon.d.mts +38 -4
- package/dist/esm/components/code-block/code-block-icon.mjs +25 -1
- package/dist/esm/components/code-block/code-block.d.mts +1 -1
- package/dist/esm/components/code-block/code-block.mjs +3 -9
- package/dist/esm/components/code-block/directory-tree-item.d.mts +15 -0
- package/dist/esm/components/code-block/directory-tree-item.mjs +8 -0
- package/dist/esm/components/code-block/directory-tree.d.mts +13 -0
- package/dist/esm/components/code-block/directory-tree.mjs +13 -0
- package/dist/esm/components/code-block/parse-tree-output.d.mts +26 -0
- package/dist/esm/components/code-block/parse-tree-output.mjs +87 -0
- package/dist/esm/components/code-block/shiki.mjs +21 -8
- package/dist/esm/components/gist/gist.d.mts +6 -0
- package/dist/esm/components/gist/gist.mjs +25 -0
- package/dist/esm/components/heading/heading.d.mts +6 -0
- package/dist/esm/components/heading/heading.mjs +9 -0
- package/dist/esm/components/image/image.mjs +1 -2
- package/dist/esm/components/link/link.mjs +1 -1
- package/dist/esm/components/link-card/link-card.mjs +1 -2
- package/dist/esm/components/mermaid/mermaid.d.mts +6 -0
- package/dist/esm/components/{code-block/code-block-mermaid.mjs → mermaid/mermaid.mjs} +6 -5
- package/dist/esm/components/youtube/youtube.mjs +1 -1
- package/dist/esm/index.d.mts +4 -1
- package/dist/esm/index.mjs +22 -1
- package/package.json +23 -36
- package/dist/cjs/components/code-block/code-block-kifu.d.ts +0 -9
- package/dist/cjs/components/code-block/code-block-mermaid.d.ts +0 -8
- package/dist/cjs/components/index.d.ts +0 -9
- package/dist/cjs/components/kifu-to/kifu-to.d.ts +0 -6
- package/dist/esm/components/code-block/code-block-kifu.d.mts +0 -9
- package/dist/esm/components/code-block/code-block-kifu.mjs +0 -36
- package/dist/esm/components/code-block/code-block-mermaid.d.mts +0 -8
- package/dist/esm/components/index.d.mts +0 -9
- package/dist/esm/components/index.mjs +0 -16
- package/dist/esm/components/kifu-to/kifu-to.d.mts +0 -6
- package/dist/esm/components/kifu-to/kifu-to.mjs +0 -11
- package/dist/style.module.css +0 -280
- package/dist/style.module.scss.d.ts +0 -9
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
type CodeBlockCopyButtonProps = {
|
|
4
4
|
code: string;
|
|
5
|
-
}
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* コードブロック用のコピー ボタンコンポーネント。
|
|
8
|
+
*
|
|
9
|
+
* 与えられた code をクリップボードに書き込み、コピー完了時にアイコンをチェックに切り替えます。
|
|
10
|
+
*
|
|
11
|
+
* @param props.code コピー対象のコード文字列(Shiki 注釈が含まれている可能性あり)。
|
|
12
|
+
* @returns コピー用ボタンの React 要素。
|
|
13
|
+
*
|
|
14
|
+
* @remarks
|
|
15
|
+
* ブラウザの navigator.clipboard を使用します。ユーザーの環境によっては権限や HTTPS が必要です。
|
|
16
|
+
*/
|
|
6
17
|
declare function CodeBlockCopyButton({ code }: CodeBlockCopyButtonProps): React.JSX.Element;
|
|
7
18
|
|
|
8
19
|
export { type CodeBlockCopyButtonProps, CodeBlockCopyButton as default };
|
|
@@ -34,14 +34,14 @@ __export(code_block_copy_button_exports, {
|
|
|
34
34
|
module.exports = __toCommonJS(code_block_copy_button_exports);
|
|
35
35
|
var import_react = __toESM(require("react"));
|
|
36
36
|
var import_hi2 = require("react-icons/hi2");
|
|
37
|
+
const removeShikiCode = (code) => code.replace(/ *\/\/.*\[!code[^\]]+\]/gm, "").trim();
|
|
37
38
|
function CodeBlockCopyButton({ code }) {
|
|
38
39
|
const [copied, setCopied] = (0, import_react.useState)(false);
|
|
39
|
-
const removeShikiCode = (code2) => code2.replace(/ *\/\/.*\[!code[^\]]+\]/gm, "").trim();
|
|
40
40
|
const handleClick = () => {
|
|
41
41
|
navigator.clipboard.writeText(removeShikiCode(code)).then(() => {
|
|
42
42
|
setCopied(true);
|
|
43
43
|
setTimeout(() => setCopied(false), 1e3);
|
|
44
44
|
});
|
|
45
45
|
};
|
|
46
|
-
return /* @__PURE__ */ import_react.default.createElement("button", { onClick: handleClick }, copied ? /* @__PURE__ */ import_react.default.createElement(import_hi2.HiCheck, { size: 18 }) : /* @__PURE__ */ import_react.default.createElement(import_hi2.HiOutlineClipboardDocumentList, { size: 18 }));
|
|
46
|
+
return /* @__PURE__ */ import_react.default.createElement("button", { onClick: handleClick, "aria-label": "Copy code to clipboard" }, copied ? /* @__PURE__ */ import_react.default.createElement(import_hi2.HiCheck, { size: 18 }) : /* @__PURE__ */ import_react.default.createElement(import_hi2.HiOutlineClipboardDocumentList, { size: 18 }));
|
|
47
47
|
}
|
|
@@ -1,8 +1,42 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { JSX } from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* CodeBlockIcon コンポーネントの props 型定義。
|
|
5
|
+
*
|
|
6
|
+
* `language` プロパティに基づいて、コードブロックに表示する代表的なアイコンを返します。
|
|
7
|
+
* 小文字の言語識別子(例: `"typescript"`, `"bash"`, `"json"`, `"markdown"`)を想定しています。
|
|
8
|
+
* 未知の値やサポート外の値は汎用のコードアイコンにフォールバックします。
|
|
9
|
+
*/
|
|
10
|
+
type CodeBlockIconProps = {
|
|
11
|
+
/**
|
|
12
|
+
* アイコン選択に用いる言語識別子(小文字推奨)。例: 'typescript', 'bash', 'json'
|
|
13
|
+
*/
|
|
4
14
|
language: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* 指定された言語に対応するアイコンを返すコンポーネント。
|
|
18
|
+
*
|
|
19
|
+
* 共通の言語識別子を `react-icons` のアイコンにマッピングします。
|
|
20
|
+
* 認識できない言語は汎用の括弧(コード)アイコンに置き換わります。
|
|
21
|
+
*
|
|
22
|
+
* 使用例:
|
|
23
|
+
*
|
|
24
|
+
* ```tsx
|
|
25
|
+
* <CodeBlockIcon language="typescript" />
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* サポート例(非網羅):
|
|
29
|
+
* - 'bash' | 'sh' -> ターミナルアイコン
|
|
30
|
+
* - 'typescript' -> TypeScript アイコン
|
|
31
|
+
* - 'tsx' -> React アイコン
|
|
32
|
+
* - 'json' -> JSON アイコン
|
|
33
|
+
* - 'markdown' -> Markdown アイコン
|
|
34
|
+
* - 'hcl' -> Terraform アイコン
|
|
35
|
+
* - 'php', 'ruby', 'yaml', 'text' など
|
|
36
|
+
*
|
|
37
|
+
* @param props.language アイコン選択に用いる小文字の言語名
|
|
38
|
+
* @returns 選択されたアイコンを含む JSX 要素
|
|
39
|
+
*/
|
|
40
|
+
declare function CodeBlockIcon({ language }: CodeBlockIconProps): JSX.Element;
|
|
7
41
|
|
|
8
42
|
export { type CodeBlockIconProps, CodeBlockIcon as default };
|
|
@@ -42,6 +42,18 @@ function CodeBlockIcon({ language }) {
|
|
|
42
42
|
case "sh":
|
|
43
43
|
case "bash":
|
|
44
44
|
return /* @__PURE__ */ import_react.default.createElement(import_fa6.FaTerminal, null);
|
|
45
|
+
case "js":
|
|
46
|
+
case "javascript":
|
|
47
|
+
return /* @__PURE__ */ import_react.default.createElement(import_si.SiJavascript, null);
|
|
48
|
+
case "py":
|
|
49
|
+
case "python":
|
|
50
|
+
return /* @__PURE__ */ import_react.default.createElement(import_si.SiPython, null);
|
|
51
|
+
case "kotlin":
|
|
52
|
+
return /* @__PURE__ */ import_react.default.createElement(import_si.SiKotlin, null);
|
|
53
|
+
case "go":
|
|
54
|
+
return /* @__PURE__ */ import_react.default.createElement(import_si.SiGo, null);
|
|
55
|
+
case "rust":
|
|
56
|
+
return /* @__PURE__ */ import_react.default.createElement(import_si.SiRust, null);
|
|
45
57
|
case "hcl":
|
|
46
58
|
return /* @__PURE__ */ import_react.default.createElement(import_si.SiTerraform, null);
|
|
47
59
|
case "typescript":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { CodeBlockComponentProps } from '@hackersheet/react-document-content';
|
|
3
3
|
|
|
4
|
-
declare function CodeBlock({ code,
|
|
4
|
+
declare function CodeBlock({ code, ...props }: CodeBlockComponentProps): Promise<React.JSX.Element>;
|
|
5
5
|
|
|
6
6
|
export { CodeBlock as default };
|
|
@@ -34,15 +34,9 @@ module.exports = __toCommonJS(code_block_exports);
|
|
|
34
34
|
var import_react = __toESM(require("react"));
|
|
35
35
|
var import_code_block_copy_button = __toESM(require("./code-block-copy-button"));
|
|
36
36
|
var import_code_block_icon = __toESM(require("./code-block-icon"));
|
|
37
|
-
var import_code_block_kifu = __toESM(require("./code-block-kifu"));
|
|
38
|
-
var import_code_block_mermaid = __toESM(require("./code-block-mermaid"));
|
|
39
37
|
var import_shiki = require("./shiki");
|
|
40
|
-
async function CodeBlock({ code,
|
|
41
|
-
const [
|
|
42
|
-
const
|
|
43
|
-
const isKifu = lang === "kifu";
|
|
44
|
-
if (isMermaid) return /* @__PURE__ */ import_react.default.createElement(import_code_block_mermaid.default, { code });
|
|
45
|
-
if (isKifu) return /* @__PURE__ */ import_react.default.createElement(import_code_block_kifu.default, { kifu: code, filename });
|
|
46
|
-
const html = await (0, import_shiki.highlighteCode)(code, lang);
|
|
38
|
+
async function CodeBlock({ code, ...props }) {
|
|
39
|
+
const [language, filename] = props.language.split(":");
|
|
40
|
+
const html = await (0, import_shiki.highlighteCode)(code, language);
|
|
47
41
|
return /* @__PURE__ */ import_react.default.createElement("div", { className: "code-block" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "code-block-header" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement(import_code_block_icon.default, { language })), /* @__PURE__ */ import_react.default.createElement("div", { className: "code-block-filename" }, filename), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement(import_code_block_copy_button.default, { code }))), html && /* @__PURE__ */ import_react.default.createElement("div", { dangerouslySetInnerHTML: { __html: html } }), !html && /* @__PURE__ */ import_react.default.createElement("pre", null, code));
|
|
48
42
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TreeNode } from './parse-tree-output.js';
|
|
3
|
+
|
|
4
|
+
type DirectoryTreeItemProps = {
|
|
5
|
+
node: TreeNode;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* 単一のツリーノード(ディレクトリまたはファイル)をレンダリングするコンポーネント。
|
|
9
|
+
* 再帰的に自身を呼び出して子ノードを描画します。
|
|
10
|
+
*
|
|
11
|
+
* @param props.node - 表示対象の TreeNode
|
|
12
|
+
*/
|
|
13
|
+
declare function DirectoryTreeItem({ node }: DirectoryTreeItemProps): React.JSX.Element;
|
|
14
|
+
|
|
15
|
+
export { DirectoryTreeItem as default };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var directory_tree_item_exports = {};
|
|
30
|
+
__export(directory_tree_item_exports, {
|
|
31
|
+
default: () => DirectoryTreeItem
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(directory_tree_item_exports);
|
|
34
|
+
var import_react = __toESM(require("react"));
|
|
35
|
+
var import_lu = require("react-icons/lu");
|
|
36
|
+
function DirectoryTreeItem({ node }) {
|
|
37
|
+
return /* @__PURE__ */ import_react.default.createElement("li", { key: node.id, className: `${node.type === "directory" ? "directory-tree-directory" : "directory-tree-file"}` }, /* @__PURE__ */ import_react.default.createElement("div", { className: "directory-tree-node-content" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "directory-tree-icon" }, node.type === "directory" && /* @__PURE__ */ import_react.default.createElement(import_lu.LuFolder, null), node.type === "file" && /* @__PURE__ */ import_react.default.createElement(import_lu.LuFile, null)), /* @__PURE__ */ import_react.default.createElement("div", null, node.name)), node.children && /* @__PURE__ */ import_react.default.createElement("ul", null, node.children.map((child) => /* @__PURE__ */ import_react.default.createElement(DirectoryTreeItem, { key: child.id, node: child }))));
|
|
38
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { DirectoryTreeComponentProps } from '@hackersheet/react-document-content';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* code ブロック内の `tree` コマンド出力をパースしてツリーをレンダリングするコンポーネント。
|
|
6
|
+
* ヘッダにはツリーアイコン、ファイル名(language のコロン以降)、コピー用ボタンを表示します。
|
|
7
|
+
*
|
|
8
|
+
* @param props.code - `tree` コマンドの出力テキスト
|
|
9
|
+
* @param props.language - 言語/ファイル名情報(形式: "xxx:filename")
|
|
10
|
+
*/
|
|
11
|
+
declare function DirectoryTree({ code, ...props }: DirectoryTreeComponentProps): Promise<React.JSX.Element>;
|
|
12
|
+
|
|
13
|
+
export { DirectoryTree as default };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
"use client";
|
|
3
2
|
var __create = Object.create;
|
|
4
3
|
var __defProp = Object.defineProperty;
|
|
5
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -27,40 +26,18 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
26
|
mod
|
|
28
27
|
));
|
|
29
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
-
var
|
|
31
|
-
__export(
|
|
32
|
-
default: () =>
|
|
29
|
+
var directory_tree_exports = {};
|
|
30
|
+
__export(directory_tree_exports, {
|
|
31
|
+
default: () => DirectoryTree
|
|
33
32
|
});
|
|
34
|
-
module.exports = __toCommonJS(
|
|
35
|
-
var import_kifu_for_js = require("kifu-for-js");
|
|
36
|
-
var import_navigation = require("next/navigation");
|
|
33
|
+
module.exports = __toCommonJS(directory_tree_exports);
|
|
37
34
|
var import_react = __toESM(require("react"));
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
(
|
|
46
|
-
const newPly = Number(searchParams.get("ply") ?? 0);
|
|
47
|
-
const hash = typeof window !== "undefined" ? window.location.hash.replace(/^#!?/, "") : "";
|
|
48
|
-
if (hash === id) {
|
|
49
|
-
kifuStore.player.goto(newPly);
|
|
50
|
-
}
|
|
51
|
-
}, [searchParams, kifuStore, id]);
|
|
52
|
-
if (!kifuStore) {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
return /* @__PURE__ */ import_react.default.createElement("div", { className: "my-4 flex justify-center", id }, /* @__PURE__ */ import_react.default.createElement(import_kifu_for_js.KifuLite, { style: { width: "100%" }, kifuStore }));
|
|
56
|
-
}
|
|
57
|
-
function initKifuUserSettings() {
|
|
58
|
-
const LOCALSTORAGE_KEY = "kifuforjs";
|
|
59
|
-
const defaultSettings = {
|
|
60
|
-
hapticFeedback: false
|
|
61
|
-
};
|
|
62
|
-
const settings = localStorage.getItem(LOCALSTORAGE_KEY);
|
|
63
|
-
if (!settings) {
|
|
64
|
-
localStorage.setItem(LOCALSTORAGE_KEY, JSON.stringify(defaultSettings));
|
|
65
|
-
}
|
|
35
|
+
var import_lu = require("react-icons/lu");
|
|
36
|
+
var import_code_block_copy_button = __toESM(require("./code-block-copy-button"));
|
|
37
|
+
var import_directory_tree_item = __toESM(require("./directory-tree-item"));
|
|
38
|
+
var import_parse_tree_output = __toESM(require("./parse-tree-output"));
|
|
39
|
+
async function DirectoryTree({ code, ...props }) {
|
|
40
|
+
const [, filename] = props.language.split(":");
|
|
41
|
+
const treeNode = (0, import_parse_tree_output.default)(code);
|
|
42
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { className: "code-block" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "code-block-header" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement(import_lu.LuFolderTree, null)), /* @__PURE__ */ import_react.default.createElement("div", { className: "code-block-filename" }, filename), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement(import_code_block_copy_button.default, { code }))), /* @__PURE__ */ import_react.default.createElement("div", null, treeNode ? /* @__PURE__ */ import_react.default.createElement("ul", { className: "directory-tree" }, /* @__PURE__ */ import_react.default.createElement(import_directory_tree_item.default, { node: treeNode })) : /* @__PURE__ */ import_react.default.createElement("pre", null, code)));
|
|
66
43
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
type TreeNode = {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
type: 'file' | 'directory';
|
|
5
|
+
extension?: string;
|
|
6
|
+
level: number;
|
|
7
|
+
children?: TreeNode[];
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* `tree` コマンドの出力(box-drawing を含むテキスト)をパースして TreeNode のツリー構造を返します。
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* - 入力は Linux/macOS の `tree` コマンドの標準出力を想定しています。
|
|
14
|
+
* - 行先頭の箱線文字(`│`, `├`, `└`, `─`)や 4 スペースインデントを解析して階層を決定します。
|
|
15
|
+
* - 最後に出力されるサマリ行(例: `3 directories, 5 files`)は自動的に除外します。
|
|
16
|
+
* - 子要素が存在する行のみをディレクトリと見なすルールを採用しています(子要素が無ければファイル)。
|
|
17
|
+
* - 解析中に例外が発生した場合は `null` を返します(呼び出し元でフォールバック処理を行ってください)。
|
|
18
|
+
*
|
|
19
|
+
* @param treeOutput - `tree` コマンドで得られたテキスト全体
|
|
20
|
+
* @returns 解析に成功した場合はルート `TreeNode`、失敗または空入力の場合は `null`
|
|
21
|
+
*
|
|
22
|
+
* @complexity O(n) - 入力行数 n に対して一度の走査で処理します(追加で逆順集計を行うためメモリは O(n))。
|
|
23
|
+
*/
|
|
24
|
+
declare function parseTreeOutput(treeOutput: string): TreeNode | null;
|
|
25
|
+
|
|
26
|
+
export { type TreeNode, parseTreeOutput as default, parseTreeOutput };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var parse_tree_output_exports = {};
|
|
20
|
+
__export(parse_tree_output_exports, {
|
|
21
|
+
default: () => parse_tree_output_default,
|
|
22
|
+
parseTreeOutput: () => parseTreeOutput
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(parse_tree_output_exports);
|
|
25
|
+
var import_crypto = require("crypto");
|
|
26
|
+
function encryptSha256(str) {
|
|
27
|
+
const hash = (0, import_crypto.createHash)("sha256");
|
|
28
|
+
hash.update(str);
|
|
29
|
+
return hash.digest("hex");
|
|
30
|
+
}
|
|
31
|
+
function parseTreeOutput(treeOutput) {
|
|
32
|
+
const raw = treeOutput.replace(/\r/g, "").trim();
|
|
33
|
+
if (!raw) return null;
|
|
34
|
+
const lines = raw.split("\n");
|
|
35
|
+
const filteredLines = lines.filter(
|
|
36
|
+
(l) => !/^\s*(?:\d+\s+directories?,\s*\d+\s+files?|\d+\s+directories?|\d+\s+files?)\s*$/i.test(l)
|
|
37
|
+
);
|
|
38
|
+
const idPrefix = "tree-" + encryptSha256(raw) + "-";
|
|
39
|
+
const rootNode = {
|
|
40
|
+
id: idPrefix + "root",
|
|
41
|
+
name: "",
|
|
42
|
+
type: "directory",
|
|
43
|
+
level: 0,
|
|
44
|
+
children: []
|
|
45
|
+
};
|
|
46
|
+
const stack = [{ node: rootNode, level: 0 }];
|
|
47
|
+
const getExtension = (filename) => filename.match(/\.(\w+)$/)?.[1];
|
|
48
|
+
const cleanNodeName = (name) => name.replace(/^[\s│├└─]+/, "").trim();
|
|
49
|
+
try {
|
|
50
|
+
const treeLineRegex = /^(?<prefix>(?:│\s{3}|\s{4})*)(?<connector>├── |└── )?(?<name>.*)$/;
|
|
51
|
+
const lineInfos = filteredLines.map((ln) => {
|
|
52
|
+
const normalized = ln.replace(/\t/g, " ");
|
|
53
|
+
const m = normalized.match(treeLineRegex);
|
|
54
|
+
if (m && m.groups) {
|
|
55
|
+
const prefix = m.groups["prefix"] || "";
|
|
56
|
+
const connector = m.groups["connector"] || "";
|
|
57
|
+
const name = (m.groups["name"] || "").trim();
|
|
58
|
+
const groupMatches = prefix.match(/(?:│\s{3}|\s{4})/g);
|
|
59
|
+
const level = (groupMatches ? groupMatches.length : 0) + (connector ? 1 : 0);
|
|
60
|
+
return { rawLine: normalized, level, cleanedName: cleanNodeName(name) };
|
|
61
|
+
}
|
|
62
|
+
return { rawLine: normalized, level: 0, cleanedName: cleanNodeName(normalized.trim()) };
|
|
63
|
+
});
|
|
64
|
+
const reduceResult = lineInfos.reduceRight(
|
|
65
|
+
(acc, info) => ({
|
|
66
|
+
lastLevel: info.rawLine.trim() ? info.level : acc.lastLevel,
|
|
67
|
+
nextLevels: [acc.lastLevel, ...acc.nextLevels]
|
|
68
|
+
}),
|
|
69
|
+
{ lastLevel: null, nextLevels: [] }
|
|
70
|
+
);
|
|
71
|
+
const nextNonEmptyLevel = reduceResult.nextLevels;
|
|
72
|
+
lineInfos.forEach((info, index) => {
|
|
73
|
+
const level = info.level;
|
|
74
|
+
const cleanedLine = info.cleanedName;
|
|
75
|
+
if (level === 0 && rootNode.name === "") {
|
|
76
|
+
rootNode.name = cleanedLine;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const nextLevelForLine = nextNonEmptyLevel[index];
|
|
80
|
+
const isDirectory = nextLevelForLine != null && nextLevelForLine > level;
|
|
81
|
+
const newNode = {
|
|
82
|
+
id: idPrefix + "node-" + index,
|
|
83
|
+
name: cleanedLine,
|
|
84
|
+
type: isDirectory ? "directory" : "file",
|
|
85
|
+
extension: isDirectory ? void 0 : getExtension(cleanedLine),
|
|
86
|
+
level,
|
|
87
|
+
children: isDirectory ? [] : void 0
|
|
88
|
+
};
|
|
89
|
+
while (stack.length > 0 && stack[stack.length - 1].level >= level) {
|
|
90
|
+
stack.pop();
|
|
91
|
+
}
|
|
92
|
+
if (stack[stack.length - 1] === void 0) {
|
|
93
|
+
throw new Error("Tree parsing failed");
|
|
94
|
+
}
|
|
95
|
+
const parentNode = stack[stack.length - 1].node;
|
|
96
|
+
parentNode.children = parentNode.children || [];
|
|
97
|
+
parentNode.children.push(newNode);
|
|
98
|
+
if (newNode.type === "directory") {
|
|
99
|
+
stack.push({ node: newNode, level });
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return rootNode;
|
|
103
|
+
} catch {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
var parse_tree_output_default = parseTreeOutput;
|
|
108
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
109
|
+
0 && (module.exports = {
|
|
110
|
+
parseTreeOutput
|
|
111
|
+
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
var shiki_exports = {};
|
|
20
30
|
__export(shiki_exports, {
|
|
@@ -23,27 +33,35 @@ __export(shiki_exports, {
|
|
|
23
33
|
module.exports = __toCommonJS(shiki_exports);
|
|
24
34
|
var import_transformers = require("@shikijs/transformers");
|
|
25
35
|
var import_react = require("react");
|
|
26
|
-
var
|
|
36
|
+
var import_web = require("shiki/bundle/web");
|
|
37
|
+
var import_javascript = require("shiki/engine/javascript");
|
|
27
38
|
async function highlighteCode(code, language) {
|
|
28
39
|
const highlighter = await getShikiHighlighter();
|
|
29
|
-
const
|
|
40
|
+
const shikiLangs = highlighter.getLoadedLanguages();
|
|
41
|
+
const shikiLang = shikiLangs.find((lang) => lang === language);
|
|
30
42
|
if (shikiLang === void 0 && language !== "text") {
|
|
31
43
|
return null;
|
|
32
44
|
}
|
|
33
|
-
const html = highlighter.codeToHtml(code, {
|
|
45
|
+
const html = highlighter.codeToHtml(code.trim(), {
|
|
34
46
|
lang: shikiLang || "text",
|
|
35
47
|
themes: {
|
|
36
48
|
light: "github-light",
|
|
37
49
|
dark: "github-dark-dimmed"
|
|
38
50
|
},
|
|
39
|
-
transformers: [
|
|
51
|
+
transformers: [
|
|
52
|
+
(0, import_transformers.transformerNotationDiff)(),
|
|
53
|
+
(0, import_transformers.transformerNotationHighlight)(),
|
|
54
|
+
(0, import_transformers.transformerNotationWordHighlight)(),
|
|
55
|
+
(0, import_transformers.transformerRemoveNotationEscape)()
|
|
56
|
+
]
|
|
40
57
|
});
|
|
41
58
|
return html;
|
|
42
59
|
}
|
|
43
60
|
const getShikiHighlighter = (0, import_react.cache)(async () => {
|
|
44
|
-
return (0,
|
|
45
|
-
themes:
|
|
46
|
-
langs: Object.
|
|
61
|
+
return (0, import_web.getSingletonHighlighterCore)({
|
|
62
|
+
themes: [import("@shikijs/themes/github-light"), import("@shikijs/themes/github-dark-dimmed")],
|
|
63
|
+
langs: Object.values(import_web.bundledLanguages),
|
|
64
|
+
engine: (0, import_javascript.createJavaScriptRegexEngine)()
|
|
47
65
|
});
|
|
48
66
|
});
|
|
49
67
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -26,31 +26,30 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
mod
|
|
27
27
|
));
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
var
|
|
30
|
-
__export(
|
|
31
|
-
|
|
32
|
-
Image: () => import_image.default,
|
|
33
|
-
KifuTo: () => import_kifu_to.default,
|
|
34
|
-
Link: () => import_link.default,
|
|
35
|
-
LinkCard: () => import_link_card.default,
|
|
36
|
-
XPost: () => import_x_post.default,
|
|
37
|
-
Youtube: () => import_youtube.default
|
|
38
|
-
});
|
|
39
|
-
module.exports = __toCommonJS(components_exports);
|
|
40
|
-
var import_code_block = __toESM(require("./code-block/code-block"));
|
|
41
|
-
var import_image = __toESM(require("./image/image"));
|
|
42
|
-
var import_kifu_to = __toESM(require("./kifu-to/kifu-to"));
|
|
43
|
-
var import_link = __toESM(require("./link/link"));
|
|
44
|
-
var import_link_card = __toESM(require("./link-card/link-card"));
|
|
45
|
-
var import_x_post = __toESM(require("./x-post/x-post"));
|
|
46
|
-
var import_youtube = __toESM(require("./youtube/youtube"));
|
|
47
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
48
|
-
0 && (module.exports = {
|
|
49
|
-
CodeBlock,
|
|
50
|
-
Image,
|
|
51
|
-
KifuTo,
|
|
52
|
-
Link,
|
|
53
|
-
LinkCard,
|
|
54
|
-
XPost,
|
|
55
|
-
Youtube
|
|
29
|
+
var gist_exports = {};
|
|
30
|
+
__export(gist_exports, {
|
|
31
|
+
default: () => Gist
|
|
56
32
|
});
|
|
33
|
+
module.exports = __toCommonJS(gist_exports);
|
|
34
|
+
var import_script = __toESM(require("next/script"));
|
|
35
|
+
var import_react = __toESM(require("react"));
|
|
36
|
+
async function Gist({ gistId, username, filename }) {
|
|
37
|
+
const gistUrl = (() => {
|
|
38
|
+
const base = `https://gist.github.com/${username}/${gistId}.json`;
|
|
39
|
+
if (filename) {
|
|
40
|
+
return base + `?file=${filename}`;
|
|
41
|
+
}
|
|
42
|
+
return base;
|
|
43
|
+
})();
|
|
44
|
+
const result = await fetch(gistUrl);
|
|
45
|
+
const json = await result.json();
|
|
46
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(
|
|
47
|
+
"div",
|
|
48
|
+
{
|
|
49
|
+
className: "gist-block",
|
|
50
|
+
dangerouslySetInnerHTML: {
|
|
51
|
+
__html: json.div
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
), /* @__PURE__ */ import_react.default.createElement(import_script.default, { stylesheets: [json.stylesheet] }));
|
|
55
|
+
}
|
|
@@ -26,16 +26,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
mod
|
|
27
27
|
));
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
var
|
|
30
|
-
__export(
|
|
31
|
-
default: () =>
|
|
29
|
+
var heading_exports = {};
|
|
30
|
+
__export(heading_exports, {
|
|
31
|
+
default: () => Heading
|
|
32
32
|
});
|
|
33
|
-
module.exports = __toCommonJS(
|
|
33
|
+
module.exports = __toCommonJS(heading_exports);
|
|
34
34
|
var import_link = __toESM(require("next/link"));
|
|
35
35
|
var import_react = __toESM(require("react"));
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const label = defaultLabel ?? `${ply}\u624B\u76EE`;
|
|
40
|
-
return /* @__PURE__ */ import_react.default.createElement(import_link.default, { href }, label);
|
|
36
|
+
var import_md = require("react-icons/md");
|
|
37
|
+
function Heading({ HeadingTag, id, children }) {
|
|
38
|
+
return /* @__PURE__ */ import_react.default.createElement(HeadingTag, { id, className: "heading" }, /* @__PURE__ */ import_react.default.createElement(import_link.default, { href: `#${id}`, prefetch: false }, /* @__PURE__ */ import_react.default.createElement("span", { className: "heading-label" }, children), /* @__PURE__ */ import_react.default.createElement("span", { className: "heading-link-icon" }, /* @__PURE__ */ import_react.default.createElement(import_md.MdLink, null))));
|
|
41
39
|
}
|
|
@@ -31,8 +31,7 @@ __export(image_exports, {
|
|
|
31
31
|
default: () => Image
|
|
32
32
|
});
|
|
33
33
|
module.exports = __toCommonJS(image_exports);
|
|
34
|
-
var import_image = __toESM(require("next/image"));
|
|
35
34
|
var import_react = __toESM(require("react"));
|
|
36
35
|
function Image({ src, width, height, alt }) {
|
|
37
|
-
return /* @__PURE__ */ import_react.default.createElement(
|
|
36
|
+
return /* @__PURE__ */ import_react.default.createElement("picture", null, /* @__PURE__ */ import_react.default.createElement("img", { src, width, height, alt }));
|
|
38
37
|
}
|
|
@@ -34,5 +34,5 @@ module.exports = __toCommonJS(link_exports);
|
|
|
34
34
|
var import_link = __toESM(require("next/link"));
|
|
35
35
|
var import_react = __toESM(require("react"));
|
|
36
36
|
function Link({ href, id, children }) {
|
|
37
|
-
return /* @__PURE__ */ import_react.default.createElement(import_link.default, { href, id }, children);
|
|
37
|
+
return /* @__PURE__ */ import_react.default.createElement(import_link.default, { href, id, prefetch: false }, children);
|
|
38
38
|
}
|
|
@@ -31,7 +31,6 @@ __export(link_card_exports, {
|
|
|
31
31
|
default: () => LinkCard
|
|
32
32
|
});
|
|
33
33
|
module.exports = __toCommonJS(link_card_exports);
|
|
34
|
-
var import_image = __toESM(require("next/image"));
|
|
35
34
|
var import_react = __toESM(require("react"));
|
|
36
35
|
function LinkCard({
|
|
37
36
|
domain,
|
|
@@ -43,5 +42,5 @@ function LinkCard({
|
|
|
43
42
|
imageWidth
|
|
44
43
|
}) {
|
|
45
44
|
const faviconUrl = `https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://${domain}&size=16`;
|
|
46
|
-
return /* @__PURE__ */ import_react.default.createElement("a", { href: url, className: "link-card" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "link-card-main" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "link-card-title" }, title), /* @__PURE__ */ import_react.default.createElement("div", { className: "link-card-description" }, description), /* @__PURE__ */ import_react.default.createElement("div", { className: "link-card-domain" }, /* @__PURE__ */ import_react.default.createElement("picture", null, /* @__PURE__ */ import_react.default.createElement("img", { src: faviconUrl, alt: `${domain} favicon`, width: 16, height: 16 })), /* @__PURE__ */ import_react.default.createElement("div", null, domain))), imageUrl && /* @__PURE__ */ import_react.default.createElement("
|
|
45
|
+
return /* @__PURE__ */ import_react.default.createElement("a", { href: url, className: "link-card" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "link-card-main" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "link-card-title-container" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "link-card-title" }, title)), /* @__PURE__ */ import_react.default.createElement("div", { className: "link-card-description" }, description), /* @__PURE__ */ import_react.default.createElement("div", { className: "link-card-domain" }, /* @__PURE__ */ import_react.default.createElement("picture", null, /* @__PURE__ */ import_react.default.createElement("img", { src: faviconUrl, alt: `${domain} favicon`, width: 16, height: 16 })), /* @__PURE__ */ import_react.default.createElement("div", null, domain))), imageUrl && /* @__PURE__ */ import_react.default.createElement("picture", { className: "link-card-image" }, /* @__PURE__ */ import_react.default.createElement("img", { alt: title, src: imageUrl, height: imageHeight, width: imageWidth })));
|
|
47
46
|
}
|