From f5c4671bfbad96bf346bd7e9a21fc4317b4959df Mon Sep 17 00:00:00 2001
From: Indrajith K L
Date: Sat, 3 Dec 2022 17:00:20 +0530
Subject: Adds most of the tools
---
 v_windows/v/old/vlib/vweb/assets/assets.v      | 201 +++++++++++++++++++++++++
 v_windows/v/old/vlib/vweb/assets/assets_test.v | 179 ++++++++++++++++++++++
 2 files changed, 380 insertions(+)
 create mode 100644 v_windows/v/old/vlib/vweb/assets/assets.v
 create mode 100644 v_windows/v/old/vlib/vweb/assets/assets_test.v
(limited to 'v_windows/v/old/vlib/vweb/assets')
diff --git a/v_windows/v/old/vlib/vweb/assets/assets.v b/v_windows/v/old/vlib/vweb/assets/assets.v
new file mode 100644
index 0000000..1240e41
--- /dev/null
+++ b/v_windows/v/old/vlib/vweb/assets/assets.v
@@ -0,0 +1,201 @@
+module assets
+
+// this module provides an AssetManager for combining
+// and caching javascript & css.
+import os
+import time
+import crypto.md5
+
+const (
+	unknown_asset_type_error = 'vweb.assets: unknown asset type'
+)
+
+struct AssetManager {
+mut:
+	css []Asset
+	js  []Asset
+pub mut:
+	// when true assets will be minified
+	minify bool
+	// the directory to store the cached/combined files
+	cache_dir string
+}
+
+struct Asset {
+	file_path     string
+	last_modified time.Time
+}
+
+// new_manager returns a new AssetManager
+pub fn new_manager() &AssetManager {
+	return &AssetManager{}
+}
+
+// add_css adds a css asset
+pub fn (mut am AssetManager) add_css(file string) bool {
+	return am.add('css', file)
+}
+
+// add_js adds a js asset
+pub fn (mut am AssetManager) add_js(file string) bool {
+	return am.add('js', file)
+}
+
+// combine_css returns the combined css as a string when to_file is false
+// when to_file is true it combines the css to disk and returns the path of the file
+pub fn (am AssetManager) combine_css(to_file bool) string {
+	return am.combine('css', to_file)
+}
+
+// combine_js returns the combined js as a string when to_file is false
+// when to_file is true it combines the css to disk and returns the path of the file
+pub fn (am AssetManager) combine_js(to_file bool) string {
+	return am.combine('js', to_file)
+}
+
+// include_css returns the html  tag(s) for including the css files in a page.
+// when combine is true the files are combined.
+pub fn (am AssetManager) include_css(combine bool) string {
+	return am.include('css', combine)
+}
+
+// include_js returns the html \n'
+		}
+		for asset in assets {
+			out += '\n'
+		}
+	}
+	return out
+}
+
+// dont return option until size limit is removed
+// fn (mut am AssetManager) add(asset_type, file string) ?bool {
+fn (mut am AssetManager) add(asset_type string, file string) bool {
+	if !os.exists(file) {
+		// return error('vweb.assets: cannot add asset $file, it does not exist')
+		return false
+	}
+	asset := Asset{
+		file_path: file
+		last_modified: time.Time{
+			unix: u64(os.file_last_mod_unix(file))
+		}
+	}
+	if asset_type == 'css' {
+		am.css << asset
+	} else if asset_type == 'js' {
+		am.js << asset
+	} else {
+		panic('$assets.unknown_asset_type_error ($asset_type).')
+	}
+	return true
+}
+
+fn (am AssetManager) exists(asset_type string, file string) bool {
+	assets := am.get_assets(asset_type)
+	for asset in assets {
+		if asset.file_path == file {
+			return true
+		}
+	}
+	return false
+}
+
+fn (am AssetManager) get_assets(asset_type string) []Asset {
+	if asset_type != 'css' && asset_type != 'js' {
+		panic('$assets.unknown_asset_type_error ($asset_type).')
+	}
+	assets := if asset_type == 'css' { am.css } else { am.js }
+	return assets
+}
+
+// todo: implement proper minification
+pub fn minify_css(css string) string {
+	mut lines := css.split('\n')
+	for i, _ in lines {
+		lines[i] = lines[i].trim_space()
+	}
+	return lines.join(' ')
+}
+
+// todo: implement proper minification
+pub fn minify_js(js string) string {
+	mut lines := js.split('\n')
+	for i, _ in lines {
+		lines[i] = lines[i].trim_space()
+	}
+	return lines.join(' ')
+}
diff --git a/v_windows/v/old/vlib/vweb/assets/assets_test.v b/v_windows/v/old/vlib/vweb/assets/assets_test.v
new file mode 100644
index 0000000..6170f3c
--- /dev/null
+++ b/v_windows/v/old/vlib/vweb/assets/assets_test.v
@@ -0,0 +1,179 @@
+import vweb.assets
+import os
+
+// clean_cache_dir used before and after tests that write to a cache directory.
+// Because of parallel compilation and therefore test running,
+// unique cache dirs are needed per test function.
+fn clean_cache_dir(dir string) {
+	if os.is_dir(dir) {
+		os.rmdir_all(dir) or { panic(err) }
+	}
+}
+
+fn base_cache_dir() string {
+	return os.join_path(os.temp_dir(), 'assets_test_cache')
+}
+
+fn cache_dir(test_name string) string {
+	return os.join_path(base_cache_dir(), test_name)
+}
+
+fn get_test_file_path(file string) string {
+	path := os.join_path(base_cache_dir(), file)
+	if !os.is_dir(base_cache_dir()) {
+		os.mkdir_all(base_cache_dir()) or { panic(err) }
+	}
+	if !os.exists(path) {
+		os.write_file(path, get_test_file_contents(file)) or { panic(err) }
+	}
+	return path
+}
+
+fn get_test_file_contents(file string) string {
+	contents := match file {
+		'test1.js' { '{"one": 1}\n' }
+		'test2.js' { '{"two": 2}\n' }
+		'test1.css' { '.one {\n\tcolor: #336699;\n}\n' }
+		'test2.css' { '.two {\n\tcolor: #996633;\n}\n' }
+		else { 'wibble\n' }
+	}
+	return contents
+}
+
+fn test_set_cache() {
+	mut am := assets.new_manager()
+	am.cache_dir = 'cache'
+}
+
+fn test_set_minify() {
+	mut am := assets.new_manager()
+	am.minify = true
+}
+
+fn test_add() {
+	mut am := assets.new_manager()
+	assert am.add('css', 'testx.css') == false
+	assert am.add('css', get_test_file_path('test1.css')) == true
+	assert am.add('js', get_test_file_path('test1.js')) == true
+	// assert am.add('css', get_test_file_path('test2.js')) == false // TODO: test extension on add
+}
+
+fn test_add_css() {
+	mut am := assets.new_manager()
+	assert am.add_css('testx.css') == false
+	assert am.add_css(get_test_file_path('test1.css')) == true
+	// assert am.add_css(get_test_file_path('test1.js')) == false // TODO: test extension on add
+}
+
+fn test_add_js() {
+	mut am := assets.new_manager()
+	assert am.add_js('testx.js') == false
+	assert am.add_css(get_test_file_path('test1.js')) == true
+	// assert am.add_css(get_test_file_path('test1.css')) == false // TODO: test extension on add
+}
+
+fn test_combine_css() {
+	mut am := assets.new_manager()
+	am.cache_dir = cache_dir('test_combine_css')
+	clean_cache_dir(am.cache_dir)
+	am.add_css(get_test_file_path('test1.css'))
+	am.add_css(get_test_file_path('test2.css'))
+	// TODO: How do I test non-minified, is there a "here doc" format that keeps formatting?
+	am.minify = true
+	expected := '.one { color: #336699; } .two { color: #996633; } '
+	actual := am.combine_css(false)
+	assert actual == expected
+	assert actual.contains(expected)
+	// Test cache path doesn't change when input files and minify setting do not.
+	path1 := am.combine_css(true)
+	clean_cache_dir(am.cache_dir)
+	path2 := am.combine_css(true)
+	assert path1 == path2
+	clean_cache_dir(am.cache_dir)
+}
+
+fn test_combine_js() {
+	mut am := assets.new_manager()
+	am.cache_dir = cache_dir('test_combine_js')
+	clean_cache_dir(am.cache_dir)
+	am.add_js(get_test_file_path('test1.js'))
+	am.add_js(get_test_file_path('test2.js'))
+	expected1 := '{"one": 1}'
+	expected2 := '{"two": 2}'
+	expected := expected1 + '\n' + expected2 + '\n'
+	actual := am.combine_js(false)
+	assert actual == expected
+	assert actual.contains(expected)
+	assert actual.contains(expected1)
+	assert actual.contains(expected2)
+	am.minify = true
+	clean_cache_dir(am.cache_dir)
+	expected3 := expected1 + ' ' + expected2 + ' '
+	actual2 := am.combine_js(false)
+	assert actual2 == expected3
+	assert actual2.contains(expected3)
+	// Test cache path doesn't change when input files and minify setting do not.
+	path1 := am.combine_js(true)
+	clean_cache_dir(am.cache_dir)
+	path2 := am.combine_js(true)
+	assert path1 == path2
+	clean_cache_dir(am.cache_dir)
+}
+
+fn test_include_css() {
+	mut am := assets.new_manager()
+	file1 := get_test_file_path('test1.css')
+	am.add_css(file1)
+	expected := '\n'
+	actual := am.include_css(false)
+	assert actual == expected
+	assert actual.contains(expected)
+	// Two lines of output.
+	file2 := get_test_file_path('test2.css')
+	am.add_css(file2)
+	am.cache_dir = cache_dir('test_include_css')
+	clean_cache_dir(am.cache_dir)
+	expected2 := expected + '\n'
+	actual2 := am.include_css(false)
+	assert actual2 == expected2
+	assert actual2.contains(expected2)
+	// Combined output.
+	clean_cache_dir(am.cache_dir)
+	actual3 := am.include_css(true)
+	assert actual3.contains(expected2) == false
+	assert actual3.starts_with('\n'
+	actual := am.include_js(false)
+	assert actual == expected
+	assert actual.contains(expected)
+	// Two lines of output.
+	file2 := get_test_file_path('test2.js')
+	am.add_js(file2)
+	am.cache_dir = cache_dir('test_include_js')
+	clean_cache_dir(am.cache_dir)
+	expected2 := expected + '\n'
+	actual2 := am.include_js(false)
+	assert actual2 == expected2
+	assert actual2.contains(expected2)
+	// Combined output.
+	clean_cache_dir(am.cache_dir)
+	actual3 := am.include_js(true)
+	assert actual3.contains(expected2) == false
+	assert actual3.starts_with('