diff --git a/src/tree.js b/src/tree.js
new file mode 100644
index 0000000..c90d13d
--- /dev/null
+++ b/src/tree.js
@@ -0,0 +1,115 @@
+module.exports = { gen_tree_html }
+
+function gen_tree_html (arr) {
+ const data = gen_tree_data(arr, is_gd_folder)
+ return tree_tpl(JSON.stringify(data))
+}
+
+function tree_tpl (str) {
+ return `
+
+
+
+
+
+
+ Folder Tree
+
+
+
+
+
+
+
+
+
+
+`
+}
+
+function is_gd_folder (data) {
+ return data.mimeType === 'application/vnd.google-apps.folder'
+}
+
+function gen_tree_data (data, is_folder) {
+ if (!data || !data.length) return []
+ const folders = data.filter(is_folder)
+ const files = data.filter(v => !is_folder(v))
+ const total_size = sum(files.map(v => v.size))
+ const root = {
+ title: `/根目錄 [共${files.length} 個檔案(不包括資料夾), ${format_size(total_size)}]`,
+ key: data[0].parent
+ }
+ if (!folders.length) return [root]
+ const sub_folders = folders.filter(v => v.parent === folders[0].parent)
+ sub_folders.forEach(v => {
+ sum_files(v, data, is_folder)
+ count_files(v, data, is_folder)
+ })
+ sort_folders(folders, 'count')
+ sort_folders(sub_folders, 'count')
+ folders.forEach(v => {
+ let {name, size, count, id} = v
+ if (name.length > 50) name = name.slice(0, 48) + '...'
+ v.title = `${name} | [共${count}個檔案 ${format_size(size)}]`
+ })
+ root.children = sub_folders.map(v => gen_node(v, folders))
+ return [root]
+}
+
+function sort_folders (folders, type) {
+ if (!folders || !folders.length) return
+ if (type === 'size') return folders.sort((a, b) => b.size - a.size)
+ if (type === 'count') return folders.sort((a, b) => b.count - a.count)
+}
+
+function gen_node (v, folders) {
+ const {id, title, node} = v
+ if (node) return node
+ return v.node = {
+ title,
+ key: id,
+ children: v.children || folders.filter(vv => vv.parent === id).map(vv => gen_node(vv, folders))
+ }
+}
+
+function count_files (folder, arr, is_folder) {
+ if (folder.count) return folder.count
+ const children = arr.filter(v => v.parent === folder.id)
+ return folder.count = sum(children.map(v => {
+ if (is_folder(v)) return count_files(v, arr, is_folder)
+ return 1
+ }))
+}
+
+function sum_files (folder, arr, is_folder) {
+ if (folder.size) return folder.size
+ const children = arr.filter(v => v.parent === folder.id)
+ return folder.size = sum(children.map(v => {
+ if (is_folder(v)) return sum_files(v, arr, is_folder)
+ return v.size
+ }))
+}
+
+function sum (arr) {
+ let result = 0
+ for (const v of arr) {
+ result += Number(v) || 0
+ }
+ return result
+}
+
+function format_size (n) {
+ n = Number(n)
+ if (Number.isNaN(n)) return ''
+ if (n < 0) return 'invalid size'
+ const units = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
+ let flag = 0
+ while (n >= 1024) {
+ n = n / 1024
+ flag++
+ }
+ return n.toFixed(2) + ' ' + units[flag]
+}