ChatGPTと一緒にWebサイト制作④ サイトマップ作成編

## ChatGPTでサイトマップのグラフ作成を目指す

[ChatGPTと一緒にWebサイト制作③ UML編](https://qiita.com/koji-yamauchi/items/774d0d7a445ae8562052)の続きです。

### 過去の記事

* [ChatGPTと一緒にWebサイト制作① 調査編](https://qiita.com/koji-yamauchi/items/1615a7479d482b899fee)
* [ChatGPTと一緒にWebサイト制作② ヒアリング編](https://qiita.com/koji-yamauchi/items/e01bb5b59917545a1dea)
* [ChatGPTと一緒にWebサイト制作③ UML編](https://qiita.com/koji-yamauchi/items/e01bb5b59917545a1dea)


### 私の指示

次に資料作成のため、現状のサイトマップをgraphvizで作成したいと考えています。
解析結果の`output.json`を添付しましたので、これをもとに現状サイトマップを作成してください。

ページの親子関係はURLから推測してください。

### ChatGPTの回答

以下は、`output.json`のデータを基にしたGraphvizのスクリプトです。これを使用して、現状のサイトマップを作成できます。

#### Graphvizスクリプトの生成

```javascript
const fs = require('fs');
const path = require('path');

const inputFilePath = './output.json';
const outputFilePath = './sitemap.dot';

function createSiteMap(json) {
  const items = JSON.parse(json);
  let dot = 'digraph G {\n';

  // ノードの定義
  const nodes = items.map(item => `"${item.path}" [label="${item.pageName}"];`).join('\n');
  dot += nodes + '\n';

  // エッジの定義
  items.forEach(item => {
    const parent = path.dirname(item.path);
    if (parent !== '.') {
      dot += `"${parent}" -> "${item.path}";\n`;
    }
  });

  dot += '}';

  return dot;
}

// JSONファイルを読み込み、Graphvizスクリプトに変換して保存する
function generateGraphviz() {
  const json = fs.readFileSync(inputFilePath, 'utf-8');
  const dot = createSiteMap(json);
  fs.writeFileSync(outputFilePath, dot);
  console.log(`Graphvizスクリプトが${outputFilePath}に保存されました`);
}

generateGraphviz();
```

#### スクリプトの実行

このスクリプトを実行して、Graphviz形式のサイトマップファイルを生成します。`sitemap.dot`というファイルが生成されるので、Graphvizツールを使用して可視化します。

```bash
node generateGraphviz.js
```

#### Graphvizでの可視化

```
Graphvizをインストールしていない場合は、以下のコマンドでインストールしてください。
```

##### macOS

```bash
brew install graphviz
```

##### Windows

Graphvizの公式サイトからインストーラをダウンロードしてインストールします。

##### Ubuntu

```bash
sudo apt-get install graphviz
```

#### サイトマップの描画

以下のコマンドを実行して、サイトマップを画像として出力します。

```bash
dot -Tpng sitemap.dot -o sitemap.png
```

これにより、サイト全体の構造を視覚的に確認できるサイトマップが生成されます。

### 私の指示

思った結果と違いました。
「メンバー紹介」や「代表挨拶」は「会社概要」の配下になるようにロジックを組み直してください。
pathに着目すれば、親子関係を推測できるはずです。

### ChatGPTの回答

※省略


### 私の指示

`output.json` には、 `"path": "/works/app/"` に該当するデータがありません。

このように中間のページが欠落するような場合でも、dotファイルには
`"/works/" -> "/works/app/";`
のような記述を自動的に追加できるようにロジックを修正してください。

また、グラフの向きが今は上から下ですが、左から右に変更できますか？


### ChatGPTの回答

```javascript
const fs = require('fs');
const path = require('path');

const inputFilePath = './output.json';
const outputFilePath = './sitemap.dot';

function createSiteMap(json) {
  const items = JSON.parse(json);
  let dot = 'digraph G {\n';
  dot += 'rankdir=LR;\n'; // 左から右の向きに変更

  // ノードの定義
  const nodes = items.map(item => `"${item.path}" [label="${item.pageName}"];`).join('\n');
  dot += nodes + '\n';

  // エッジの定義
  const paths = items.map(item => item.path);

  paths.forEach(currentPath => {
    const parts = currentPath.split('/').filter(part => part !== '');
    if (parts.length > 1) {
      for (let i = 1; i < parts.length; i++) {
        const parentPath = '/' + parts.slice(0, i).join('/') + '/';
        if (!paths.includes(parentPath)) {
          dot += `"${parentPath}" [label="${parentPath.split('/').slice(-2, -1)}"];\n`;
          paths.push(parentPath);
        }
        dot += `"${parentPath}" -> "${currentPath}";\n`;
      }
    } else if (currentPath !== '/') {
      dot += `"/" -> "${currentPath}";\n`;
    }
  });

  dot += '}';

  return dot;
}

// JSONファイルを読み込み、Graphvizスクリプトに変換して保存する
function generateGraphviz() {
  const json = fs.readFileSync(inputFilePath, 'utf-8');
  const dot = createSiteMap(json);
  fs.writeFileSync(outputFilePath, dot);
  console.log(`Graphvizスクリプトが${outputFilePath}に保存されました`);
}

generateGraphviz();
```

※ その他の説明省略

### 私の指示

pathが`/works/`より下層の場合はグラフ化の対象外とするように変更してください。
ただし、`/works/`と完全一致する場合は対象としたいです。

### ChatGPTの回答

```javascript
const fs = require('fs');
const path = require('path');

const inputFilePath = './output.json';
const outputFilePath = './sitemap.dot';

function createSiteMap(json) {
  const items = JSON.parse(json);
  let dot = 'digraph G {\n';
  dot += 'rankdir=LR;\n'; // 左から右の向きに変更

  // ノードの定義
  const nodes = items
    .filter(item => !(item.path.startsWith('/works/') && item.path !== '/works/'))
    .map(item => `"${item.path}" [label="${item.pageName}"];`).join('\n');
  dot += nodes + '\n';

  // エッジの定義
  const paths = items.map(item => item.path);

  paths.forEach(currentPath => {
    if (currentPath.startsWith('/works/') && currentPath !== '/works/') {
      return;
    }
    const parts = currentPath.split('/').filter(part => part !== '');
    if (parts.length > 1) {
      for (let i = 1; i < parts.length; i++) {
        const parentPath = '/' + parts.slice(0, i).join('/') + '/';
        if (!paths.includes(parentPath) && parentPath !== '/works/') {
          dot += `"${parentPath}" [label="${parentPath.split('/').slice(-2, -1)}"];\n`;
          paths.push(parentPath);
        }
        dot += `"${parentPath}" -> "${currentPath}";\n`;
      }
    } else if (currentPath !== '/') {
      dot += `"/" -> "${currentPath}";\n`;
    }
  });

  dot += '}';

  return dot;
}

// JSONファイルを読み込み、Graphvizスクリプトに変換して保存する
function generateGraphviz() {
  const json = fs.readFileSync(inputFilePath, 'utf-8');
  const dot = createSiteMap(json);
  fs.writeFileSync(outputFilePath, dot);
  console.log(`Graphvizスクリプトが${outputFilePath}に保存されました`);
}

generateGraphviz();
```

※ その他の説明省略

## まとめ

![sitemap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426622/b3005243-7251-afa7-0608-90bd37f6f218.png)

```graphviz
digraph G {
rankdir=LR;
"/about/" [label="会社概要"];
"/about/member/" [label="メンバー紹介"];
"/about/message/" [label="代表挨拶"];
"/contact/" [label="お問い合わせ"];
"/entry/" [label="応募フォーム"];
"/" [label="株式会社add more"];
"/privacy/" [label="プライバシーポリシー"];
"/recruit/designer/" [label="デザイナー 採用情報"];
"/recruit/director/" [label="ディレクター 採用情報"];
"/recruit/engineer/" [label="エンジニア 採用情報"];
"/recruit/" [label="採用情報"];
"/services/" [label="サービス"];
"/works/" [label="実績"];
"/" -> "/about/";
"/about/" -> "/about/member/";
"/about/" -> "/about/message/";
"/" -> "/contact/";
"/" -> "/entry/";
"/" -> "/privacy/";
"/recruit/" -> "/recruit/designer/";
"/recruit/" -> "/recruit/director/";
"/recruit/" -> "/recruit/engineer/";
"/" -> "/recruit/";
"/" -> "/services/";
"/" -> "/works/";
}
```

やってみたところ、あまり見やすいグラフにはならないので、Spreadsheetでコンテンツリストを見やすくするのと、ハイレベルサイトマップは手作業で調整しながらつくるのが良いかなと思いました。

データのビジュアライズという観点でいうと、いっそのことThree.jsなどをつかって少しリッチな表現に取り組んでも良いかもしれません。

## ChatGPTと一緒にWebサイト制作シリーズ

* [ChatGPTと一緒にWebサイト制作① 調査編](https://qiita.com/koji-yamauchi/items/1615a7479d482b899fee)
* [ChatGPTと一緒にWebサイト制作② ヒアリング編](https://qiita.com/koji-yamauchi/items/e01bb5b59917545a1dea)
* [ChatGPTと一緒にWebサイト制作③ UML編](https://qiita.com/koji-yamauchi/items/774d0d7a445ae8562052)
* [ChatGPTと一緒にWebサイト制作④ サイトマップ作成編](https://qiita.com/koji-yamauchi/items/4dd67868dc5b0bf903c3)