CSVデータから大量にHTMLファイルを生成する。

#概要

神戸市が提供しているオープンデータ「観光施設情報」のCSVを元にHTMLを量産します。

#制作物

・観光地一覧ページ(index.html)

![index.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43894/3d0f2b45-0ebd-3b28-773f-0fab3348423f.jpeg)

・観光地詳細ページ（place**.html）

![detail.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43894/f1465dbc-7d70-ce02-d67f-13ed13acb88a.jpeg)


#開発環境

node v9.3.0
npm v6.12.1
gulp v4.0.2

**package.json**

```json
{
  "name": "csv2html",
  "version": "0.0.1",
  "scripts": {
    "gulp": "gulp"
  },
  "devDependencies": {
    "autoprefixer": "^9.6.1",
    "csv-parser": "^2.3.2",
    "fs": "0.0.1-security",
    "gulp": "^4.0.2",
    "gulp-ejs": "^4.1.2",
    "gulp-postcss": "^8.0.0",
    "gulp-rename": "^1.4.0",
    "gulp-stylus": "^2.7.0"
  },
  "browserslist": [
    "last 2 versions",
    "ie >= 10",
    "Android >= 4"
  ]
}
```

#読み込むCSV
```
名称,名称のルビ,郵便番号,カテゴリ,住所,緯度,経度,電話番号,説明文,営業時間,定休日,URL,バリアフリー対応
```

[観光施設情報 CSVデータ](https://data.city.kobe.lg.jp/data/dataset/dataset-00000005)

#ソース
##gulpfile.js

```javascript

const gulp = require('gulp');
const postcss = require("gulp-postcss");
const autoprefixer = require('autoprefixer');
const stylus = require('gulp-stylus');
const rename = require('gulp-rename');
const ejs = require("gulp-ejs");
const fs = require('fs');
const csv = require('csv-parser');

/*-------------------------------------------------
--------------------------------------------------*/
gulp.task('stylus', function() {
    return gulp.src(['resources/stylus/**/*.styl','!resources/stylus/**/_*.styl'])
        .pipe(stylus({
            compress: true
        }))
        .pipe(postcss([
            autoprefixer({
                cascade: false
            })
        ]))
        .pipe(gulp.dest('htdocs/assets/css/'));
});

/*-------------------------------------------------
--------------------------------------------------*/
gulp.task( "ejs", function () {
    let json;
    const results = [];

    return fs.createReadStream(__dirname + '/resources/tourism_od2810.csv')
        .pipe(csv())
        .on('data', function(data){
            let zip = data['郵便番号'];
            data['郵便番号'] = zip.substr(1,3) + '-' + zip.substr(4,4);

            let cat = data['カテゴリ'];
            data['カテゴリ'] = cat.substr(1,4);
            results.push(data);
        })
        .on('end', function(){
            json = {
                item : results
            };
            gulp.src(["./resources/ejs/index.ejs"])
                .pipe(ejs(json))
                .pipe(rename(
                    {
                        extname: '.html'
                    }))
                .pipe( gulp.dest( "./htdocs" ) );

            ////////////////////////
            for(let prop in results){
                json = {
                    item : results[prop]
                };
                gulp.src(["./resources/ejs/place.ejs"])
                .pipe(ejs(json))
                .pipe(rename(
                    { 
                        basename: 'place' + prop, 
                        extname: '.html' 
                    }))
                .pipe( gulp.dest( "./htdocs" ) );
    
            }
        });
});
/*-------------------------------------------------
--------------------------------------------------*/
gulp.task('watch', function(){
    gulp.watch( 'resources/sass/**/*.scss', gulp.task('scss'));
    gulp.watch( 'resources/stylus/**/*.styl', gulp.task('stylus'));
    gulp.watch( 'resources/ejs/**/*.ejs', gulp.task('ejs'));
});

```

##観光地一覧　index.ejs

```html
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<title>神戸市観光施設情報</title>
	<link href="https://fonts.googleapis.com/css?family=Noto+Sans+JP&display=swap" rel="stylesheet">
	<link rel="stylesheet" href="assets/css/style.css">
	<script src="assets/js/script.min.js"></script>
</head>
<body>
<header>
	<div class="header-inr">
		<a class="header-logo" href="index.html">
			<h1>神戸市観光施設情報</h1>
		</a>
	</div>
</header>

<div id="contents">
	<h2>神戸市観光施設 一覧</h2>
	<table>
		<% for (var prop in item) { %>
		<tr>
			<td><a href="place<%- prop %>.html"><%- item[prop]['名称'] %></a></td>
		</tr>
		<% } %>
	</table>
				
</div>

<footer>
Copyright 2019
</footer>
</body>
</html>
```

##観光地詳細　place.ejs

```html
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<title>神戸市観光施設情報</title>
	<link href="https://fonts.googleapis.com/css?family=Noto+Sans+JP&display=swap" rel="stylesheet">
	<link rel="stylesheet" href="assets/css/style.css">
	<script src="assets/js/script.min.js"></script>
</head>
<body>
<header>
	<div class="header-inr">
		<a class="header-logo" href="index.html">
			<h1>神戸市観光施設情報</h1>
		</a>
	</div>
</header>
<ul>
	<li><a href="index.html">HOME</a></li>
	<li><%- item['名称'] %></li>
</ul>

<div id="contents">

		<h2><%- item['名称'] %></h2>
		<div><%- item['名称のルビ'] %></div>

		　
		<iframe src="http://maps.google.co.jp/maps?q=<%- item['緯度'] %>,<%- item['経度'] %>&output=embed&t=m&z=20&hl=ja" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" width="100%" height="450"></iframe>
		　
		<table>
			<tr>
				<th>郵便番号</th>
				<td><%- item['郵便番号'] %></td>
			</tr>
			<tr>
				<th>カテゴリ</th>
				<td><%- item['カテゴリ'] %></td>
			</tr>
			<tr>
				<th>住所</th>
				<td><%- item['住所'] %></td>
			</tr>
			<tr>
				<th>緯度</th>
				<td><%- item['緯度'] %></td>
			</tr>
			<tr>
				<th>経度</th>
				<td><%- item['経度'] %></td>
			</tr>
			<tr>
				<th>電話番号</th>
				<td><%- item['電話番号'] %></td>
			</tr>
			<tr>
				<th>説明文</th>
				<td><%- item['説明文'] %></td>
			</tr>
			<tr>
				<th>営業時間</th>
				<td><%- item['営業時間'] %></td>
			</tr>
			<tr>
				<th>定休日</th>
				<td><%- item['定休日'] %></td>
			</tr>
			<tr>
				<th>URL</th>
				<td><a href="<%- item['URL'] %>" target="_blank"><%- item['URL'] %></a></td>
			</tr>
			<tr>
				<th>バリアフリー対応</th>
				<td><%- item['バリアフリー対応'] %></td>
			</tr>
		</table>
				
</div>

<footer>
Copyright 2019
</footer>
</body>
</html>
```

##Stylus
```css
body
	margin 0
	padding 0
	background-color #325e91
	font-family 'Noto Sans JP', sans-serif
	color #333333

header
	padding 15px
	background #ffffff
	margin-bottom 15px
	h1
		margin 0
		padding 0
	a
		text-decoration none
		color #333333

footer
	font-size 10px
	color #ffffff
	text-align center
	padding 10px 0
	background-color #000000

#contents
	background-color #ffffff
	max-width 1200px
	width 100%
	margin 0 auto 30px auto
	padding 30px 10px

nav
	width 25%
main
	width 75%

table
	border-collapse collapse
	border-top 1px solid #cccccc
	border-left 1px solid #cccccc
	width 100%
	th
		background-color #eeeeee
		text-align left
		padding 10px
		white-space nowrap
		font-size 14px
		border-bottom 1px solid #cccccc
		border-right 1px solid #cccccc
	td
		padding 10px
		font-size 14px
		border-bottom 1px solid #cccccc
		border-right 1px solid #cccccc

ul,li
	padding 0
	list-style none

ul
	width 100%
	max-width 1200px
	margin 0 auto 10px auto

	li
		color #ffffff
		display inline-block
		&:after
			content ">"
			display inline-block
			margin-left 10px
	li:last-child:after
		display none
	li + li
		margin-left 10px
	a
		color #ffffff

```

#変換コマンド

##Stylus変換
```
npm run gulp stylus
```
##ejs変換
```
npm run gulp ejs
```
##Watch
```
npm run gulp watch
```

#リンク
[Github](https://github.com/hiron712/csv2html)