Skip to content

Commit 344d30b

Browse files
committed
initial commit
0 parents  commit 344d30b

10 files changed

Lines changed: 861 additions & 0 deletions

File tree

.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Dependencies
2+
node_modules/
3+
4+
# Logs
5+
*.log
6+
7+
# Build outputs (generated files)
8+
public/
9+
10+
# OS generated files
11+
.DS_Store
12+
.DS_Store?
13+
._*
14+
.Spotlight-V100
15+
.Trashes
16+
ehthumbs.db
17+
Thumbs.db
18+
19+
# Editor files
20+
.vscode/
21+
.idea/
22+
*.swp
23+
*.swo
24+
*~
25+
26+
# Temporary files
27+
*.tmp
28+
*.temp

README.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Shift-JIS Web Example
2+
3+
## 概要
4+
5+
現代のフロントエンド開発ワークフローとShift-JISを共存させるための実装サンプルです。
6+
7+
UTF-8で書かれたソースコードから、Shift-JISの静的HTMLをビルドし、Shift-JISとUTF-8の両方を返すAPIサーバーと連携させる、複雑なエンコーディング混在環境を再現しています。
8+
9+
## このサンプルが示すこと
10+
11+
- **ビルド時のエンコーディング変換**:
12+
- UTF-8で書かれたEJSテンプレートからShift-JIS(CP932)のHTMLファイルを生成する方法。
13+
- iconv-liteライブラリを使った、文字列からバイナリデータへのエンコード変換。
14+
- **サーバーサイドでのShift-JIS対応**:
15+
- Shift-JISのデータファイルを読み込んでWebAPIとして提供する実装方法。
16+
- 円マーク問題の実装レベルでの対処(`\``¥` 変換)。
17+
- Shift-JISでJSONレスポンスを返すための適切なヘッダー設定とエンコード処理。
18+
- **クライアントサイドでのShift-JISの扱い**:
19+
- Shift-JISのHTMLページ上で、UTF-8のJavaScriptを実行する方法(`<script charset="utf-8">`)。
20+
- Shift-JISでエンコードされたAPIレスポンスを、文字化けさせずに扱うための3つの異なる実装方法の比較。
21+
22+
## 技術スタック
23+
24+
- **ビルド**: Node.js, EJS, iconv-lite, fs-extra
25+
- **APIサーバー**: Python 3 (http.server)
26+
- **クライアントサイド**: Vanilla JavaScript, axios
27+
28+
## ディレクトリ構成
29+
30+
```
31+
sjis-web-example/
32+
├── build/ # ビルドスクリプト (`build.js`)
33+
├── public/ # Webサーバーの公開ディレクトリ(ビルド後の成果物)
34+
├── server/ # APIサーバーのスクリプト (`api_server.py`)
35+
├── src/ # 開発用のソースファイル(すべてUTF-8)
36+
├── data/ # DBの代わりとなるデータソース(Shift-JIS)
37+
└── package.json # ビルドスクリプトの依存関係
38+
```
39+
40+
## 実行手順
41+
42+
### 1. 前提条件
43+
- Node.js と npm がインストールされていること。
44+
- Python 3 がインストールされていること。
45+
46+
### 2. 依存パッケージのインストール
47+
プロジェクトのルートディレクトリで、以下のコマンドを実行します。
48+
49+
```bash
50+
npm install
51+
```
52+
53+
### 3. サーバーの起動
54+
以下のコマンドで、ビルドとPython製Webサーバーの起動を同時に実行します。
55+
このサーバーは`public/`ディレクトリのファイルを配信し、`/api`へのリクエストを処理します。
56+
57+
```bash
58+
npm start
59+
```
60+
61+
ビルドのみ実行したい場合:
62+
63+
```bash
64+
npm run build
65+
```
66+
67+
### 4. ブラウザで確認
68+
サーバーが起動したら、Webブラウザで以下のURLにアクセスしてください。
69+
70+
[http://localhost:8000](http://localhost:8000)
71+
72+
3つのShift-JIS API呼び出しパターンと、比較用のUTF-8 API呼び出しの結果が、すべて文字化けせずに表示されるはずです。

build/build.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
const fs = require('fs-extra');
2+
const path = require('path');
3+
const ejs = require('ejs');
4+
const iconv = require('iconv-lite');
5+
6+
const projectRoot = path.resolve(__dirname, '..');
7+
const srcDir = path.join(projectRoot, 'src');
8+
const publicDir = path.join(projectRoot, 'public');
9+
const templatesDir = path.join(srcDir, 'templates');
10+
11+
async function build() {
12+
try {
13+
console.log('Starting build...');
14+
15+
// publicディレクトリを空にする
16+
await fs.emptyDir(publicDir);
17+
console.log('Cleaned public directory.');
18+
19+
// 1. EJSテンプレートをHTML文字列にレンダリング(UTF-8)
20+
const templatePath = path.join(templatesDir, 'index.ejs');
21+
const templateStr = await fs.readFile(templatePath, 'utf-8');
22+
const htmlUtf8 = await ejs.render(templateStr, {}, { async: true });
23+
console.log('Rendered EJS template to HTML.');
24+
25+
// 2. HTML文字列をShift-JIS(CP932)バッファに変換
26+
const htmlSjisBuffer = iconv.encode(htmlUtf8, 'cp932');
27+
console.log('Converted HTML to Shift-JIS (CP932) buffer.');
28+
29+
// 3. Shift-JISバッファをindex.htmlに書き出し
30+
await fs.writeFile(path.join(publicDir, 'index.html'), htmlSjisBuffer);
31+
console.log('Wrote index.html (Shift-JIS).');
32+
33+
// 4. CSSとJSファイルをコピー
34+
await fs.copy(path.join(srcDir, 'css'), path.join(publicDir, 'css'));
35+
await fs.copy(path.join(srcDir, 'js'), path.join(publicDir, 'js'));
36+
console.log('Copied CSS and JS files.');
37+
38+
// 5. node_modulesからaxiosをコピー
39+
// require.resolve('axios')はpackage.jsonを指すので、そのディレクトリを取得
40+
const axiosPackageJsonPath = require.resolve('axios/package.json');
41+
const axiosRootDir = path.dirname(axiosPackageJsonPath);
42+
await fs.ensureDir(path.join(publicDir, 'js', 'vendor'));
43+
await fs.copy(
44+
path.join(axiosRootDir, 'dist', 'axios.min.js'),
45+
path.join(publicDir, 'js', 'vendor', 'axios.min.js')
46+
);
47+
console.log('Copied axios library.');
48+
49+
console.log('Build completed successfully!');
50+
51+
} catch (error) {
52+
console.error('Build failed:', error);
53+
process.exit(1);
54+
}
55+
}
56+
57+
build();

data/users.csv

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
id,displayName,note
2+
1,①㈱サンプル社,価格は\1000
3+
2,②髙サンプル名,パスはC:\temp
4+
3,③サン﨑プル社,note-3
5+
4,④℡テスト名,note-4

0 commit comments

Comments
 (0)