Skip to content

Commit

Permalink
feat: init
Browse files Browse the repository at this point in the history
  • Loading branch information
matzkoh committed Mar 21, 2019
1 parent 069e33d commit a8c5334
Show file tree
Hide file tree
Showing 17 changed files with 3,220 additions and 0 deletions.
63 changes: 63 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
orbs:
repo:
executors:
default:
docker:
- image: circleci/node:10

commands:
test:
steps:
- checkout
- restore_cache:
keys:
- &cache_key npm_cache-{{ .Branch }}
- npm_cache-

- run:
name: Install Dependencies
command: npm ci

- save_cache:
key: *cache_key
paths:
- ~/.npm

- run:
name: Run Test
command: npm test

publish:
steps:
- run:
name: Publish
command: npx semantic-release

jobs:
default:
executor: default
steps:
- test

master:
executor: default
steps:
- test
- publish

version: 2.1

workflows:
main:
jobs:
- repo/default:
filters:
branches:
ignore:
- master

- repo/master:
filters:
branches:
only:
- master
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.vscode/
node_modules/
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
save-exact = true
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# GTM JSON Converter

Google Tag Manager がエクスポートした JSON をエクセルで開ける CSV に変換します

1 行に 1 つのタグ、列は以下を出力します

1. ID (GTM 内部で使われている識別子)
2. タグ名
3. タグ
4. document.write フラグ (カスタム HTML の場合)
5. トリガー

## 使い方

clone してためす場合

```bash
$ cd gtm-json-converter
$ npm i
$ npm start gtm.json # JSON のパスを渡す
```

グローバルインストールする場合

```bash
$ npm i -g @opt-tech/gtm-json-converter
$ gtm-json-converter gtm.json # JSON のパスを渡す
```

カレントディレクトリの `[コンテナ名] エクスポート日時.csv` に保存されます
21 changes: 21 additions & 0 deletions bin/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env node

const args = process.argv.slice(2)
const { write } = require('../lib/writer')

if (args.length < 1) {
console.log('Usage:\n gtm-json-converter {file}')
process.exit()
}

const [input] = args
const res = require('..').convert(input)

write(res).then(
filepath => {
console.log(`Saved successfully: ${filepath}`)
},
err => {
console.error(err)
},
)
16 changes: 16 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const path = require('path')
const { read } = require('./reader')
const { parse } = require('./parser')
const { render } = require('./renderer')
const { getFileName, write } = require('./writer')

exports.convert = input => {
input = path.resolve(input)

const json = require(input)
const { info, tags, triggers } = read(json)
const data = render(parse(tags))
const outputFileName = path.join(path.dirname(input), getFileName(info))

return { data, outputFileName }
}
31 changes: 31 additions & 0 deletions lib/parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
function getValueByKey(list, key) {
if (!Array.isArray(list)) {
return '(Error)'
}
const item = list.find(item => item.key === key)
return item && 'value' in item ? item.value : '(Error)'
}

function getTagCells(tag) {
if (!(tag instanceof Object) || !Array.isArray(tag.parameter)) {
return ['(Error)', '(Error)']
}

return tag.type === 'html'
? [
getValueByKey(tag.parameter, 'html'),
getValueByKey(tag.parameter, 'supportDocumentWrite') === 'true' ? 'サポートする' : '',
]
: [tag.parameter.map(p => `${p.key}\n ${p.value}`).join('\n'), '']
}

function getTriggerText(tag) {
return tag.firingTriggers.map(t => t.description).join('\n')
}

exports.parse = tags => {
const header = ['ID', '名前', 'タグ', 'document.write', 'トリガー']
const body = tags.map(t => [t.tagId, t.name, ...getTagCells(t), getTriggerText(t)])

return [header, ...body]
}
51 changes: 51 additions & 0 deletions lib/reader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
exports.read = json => {
const container = json.containerVersion
const info = {
...container.container,
exportTime: json.exportTime,
}
const tags = container.tag
const triggers = container.trigger
const variables = container.variable
const builtInVariables = container.builtInVariable

const ALL_PAGES = {
triggerId: '2147479553',
name: 'All Pages',
filter: [{ type: '', parameter: [{ key: 'arg0', value: 'すべてのページ' }] }],
}

triggers.push(ALL_PAGES)

function getTriggerById(id) {
return triggers.find(item => item.triggerId === id)
}

function getFilterText(trigger) {
const arr = [trigger.type]
if (Array.isArray(trigger.filter)) {
trigger.filter.forEach(item => {
const [arg0, ...args] = item.parameter.map(p => p.value)
arr.push([arg0, item.type, ...args].join(' '))
})
}
return arr.join('\n')
}

triggers.forEach(trigger => {
trigger.filterText = getFilterText(trigger)
trigger.description = `${trigger.name}\n${trigger.filterText.replace(/^/gm, ' ')}`
})

tags.forEach(tag => {
tag.firingTriggers = tag.firingTriggerId.map(getTriggerById)
})

return {
info,
tags,
triggers,
variables,
builtInVariables,
}
}
11 changes: 11 additions & 0 deletions lib/renderer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function quote(text) {
return `"${text.replace(/"/g, '""')}"`
}

function renderRow(row) {
return row.map(quote).join(',')
}

exports.render = rows => {
return rows.map(renderRow).join('\n') + '\n'
}
17 changes: 17 additions & 0 deletions lib/writer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const fs = require('fs')
const path = require('path')

const BOM = '\ufeff'

exports.getFileName = info => {
return `[${info.name}] ${info.exportTime}.csv`
}

exports.write = async ({ data, outputFileName }) => {
data = BOM + data.replace(/(?=\n)/g, '\r')
return new Promise((resolve, reject) => {
fs.writeFile(outputFileName, data, err => {
err ? reject(err) : resolve(outputFileName)
})
})
}
Loading

0 comments on commit a8c5334

Please sign in to comment.