add tree.js
This commit is contained in:
		
							parent
							
								
									c8cc23b90e
								
							
						
					
					
						commit
						29f23d5594
					
				
							
								
								
									
										115
									
								
								src/tree.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/tree.js
									
									
									
									
									
										Normal file
									
								
							@ -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 `<!doctype html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <meta charset="utf-8">
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
 | 
				
			||||||
 | 
					    <meta name="theme-color" content="#000000">
 | 
				
			||||||
 | 
					    <title>Folder Tree</title>
 | 
				
			||||||
 | 
					    <link href="https://cdn.jsdelivr.net/gh/iwestlin/gd-utils/static/tree.min.css" rel="stylesheet">
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					    <!-- source code: https://github.com/iwestlin/foldertree/blob/master/app.jsx -->
 | 
				
			||||||
 | 
					    <div id="root"></div>
 | 
				
			||||||
 | 
					    <script type="text/javascript">
 | 
				
			||||||
 | 
					    var treedata = ${str}
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					    <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/iwestlin/gd-utils/static/tree.min.js"></script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</html>`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user