hyraft 0.1.0.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/CODE_OF_CONDUCT.md +132 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +231 -0
  6. data/exe/hyraft +5 -0
  7. data/lib/hyraft/boot/asset_preloader.rb +185 -0
  8. data/lib/hyraft/boot/preloaded_static.rb +46 -0
  9. data/lib/hyraft/boot/preloader.rb +206 -0
  10. data/lib/hyraft/cli.rb +187 -0
  11. data/lib/hyraft/compiler/compiler.rb +34 -0
  12. data/lib/hyraft/compiler/html_purifier.rb +181 -0
  13. data/lib/hyraft/compiler/javascript_library.rb +281 -0
  14. data/lib/hyraft/compiler/javascript_obfuscator.rb +141 -0
  15. data/lib/hyraft/compiler/parser.rb +27 -0
  16. data/lib/hyraft/compiler/renderer.rb +217 -0
  17. data/lib/hyraft/engine/circuit.rb +35 -0
  18. data/lib/hyraft/engine/port.rb +17 -0
  19. data/lib/hyraft/engine/source.rb +19 -0
  20. data/lib/hyraft/engine.rb +11 -0
  21. data/lib/hyraft/router/api_router.rb +65 -0
  22. data/lib/hyraft/router/web_router.rb +136 -0
  23. data/lib/hyraft/system_info.rb +26 -0
  24. data/lib/hyraft/version.rb +5 -0
  25. data/lib/hyraft.rb +48 -0
  26. data/templates/do_app/Gemfile +50 -0
  27. data/templates/do_app/Rakefile +88 -0
  28. data/templates/do_app/adapter-intake/web-app/display/pages/home/home.hyr +174 -0
  29. data/templates/do_app/adapter-intake/web-app/request/home_web_adapter.rb +19 -0
  30. data/templates/do_app/boot.rb +41 -0
  31. data/templates/do_app/framework/adapters/server/server_api_adapter.rb +51 -0
  32. data/templates/do_app/framework/adapters/server/server_web_adapter.rb +178 -0
  33. data/templates/do_app/framework/compiler/style_resolver.rb +33 -0
  34. data/templates/do_app/framework/errors/error_handler.rb +75 -0
  35. data/templates/do_app/framework/errors/templates/304.html +22 -0
  36. data/templates/do_app/framework/errors/templates/400.html +22 -0
  37. data/templates/do_app/framework/errors/templates/401.html +22 -0
  38. data/templates/do_app/framework/errors/templates/403.html +22 -0
  39. data/templates/do_app/framework/errors/templates/404.html +62 -0
  40. data/templates/do_app/framework/errors/templates/500.html +73 -0
  41. data/templates/do_app/framework/middleware/cors_middleware.rb +37 -0
  42. data/templates/do_app/infra/config/environment.rb +86 -0
  43. data/templates/do_app/infra/config/error_config.rb +80 -0
  44. data/templates/do_app/infra/config/routes/api_routes.rb +2 -0
  45. data/templates/do_app/infra/config/routes/web_routes.rb +10 -0
  46. data/templates/do_app/infra/database/sequel_connection.rb +62 -0
  47. data/templates/do_app/infra/gems/database.rb +7 -0
  48. data/templates/do_app/infra/gems/load_all.rb +4 -0
  49. data/templates/do_app/infra/gems/utilities.rb +1 -0
  50. data/templates/do_app/infra/gems/web.rb +3 -0
  51. data/templates/do_app/infra/server/api-server.ru +13 -0
  52. data/templates/do_app/infra/server/web-server.ru +32 -0
  53. data/templates/do_app/package.json +9 -0
  54. data/templates/do_app/public/favicon.ico +0 -0
  55. data/templates/do_app/public/icons/docs.svg +10 -0
  56. data/templates/do_app/public/icons/expli.svg +13 -0
  57. data/templates/do_app/public/icons/git-repo.svg +13 -0
  58. data/templates/do_app/public/icons/hexagonal-arch.svg +15 -0
  59. data/templates/do_app/public/icons/template-engine.svg +26 -0
  60. data/templates/do_app/public/images/hyr-logo.png +0 -0
  61. data/templates/do_app/public/images/hyr-logo.webp +0 -0
  62. data/templates/do_app/public/index.html +22 -0
  63. data/templates/do_app/public/styles/css/main.css +418 -0
  64. data/templates/do_app/public/styles/css/spa.css +171 -0
  65. data/templates/do_app/shared/helpers/pagination_helper.rb +44 -0
  66. data/templates/do_app/shared/helpers/response_formatter.rb +25 -0
  67. data/templates/do_app/test/acceptance/api/articles_api_acceptance_test.rb +43 -0
  68. data/templates/do_app/test/acceptance/web/articles_acceptance_test.rb +31 -0
  69. data/templates/do_app/test/acceptance/web/home_acceptance_test.rb +17 -0
  70. data/templates/do_app/test/db.rb +106 -0
  71. data/templates/do_app/test/integration/adapter-exhaust/data-gateway/sequel_articles_gateway_test.rb +79 -0
  72. data/templates/do_app/test/integration/adapter-intake/api-app/request/articles_api_adapter_test.rb +61 -0
  73. data/templates/do_app/test/integration/adapter-intake/web-app/request/articles_web_adapter_test.rb +20 -0
  74. data/templates/do_app/test/integration/adapter-intake/web-app/request/home_web_adapter_test.rb +17 -0
  75. data/templates/do_app/test/integration/database/migration_test.rb +35 -0
  76. data/templates/do_app/test/support/mock_api_adapter.rb +82 -0
  77. data/templates/do_app/test/support/mock_articles_gateway.rb +41 -0
  78. data/templates/do_app/test/support/mock_web_adapter.rb +85 -0
  79. data/templates/do_app/test/support/test_patches.rb +33 -0
  80. data/templates/do_app/test/test_helper.rb +526 -0
  81. data/templates/do_app/test/unit/engine/circuit/articles_circuit_test.rb +167 -0
  82. data/templates/do_app/test/unit/engine/port/articles_gateway_port_test.rb +12 -0
  83. data/templates/do_app/test/unit/engine/source/article_test.rb +37 -0
  84. metadata +291 -0
@@ -0,0 +1,86 @@
1
+ # infra/config/environment.rb
2
+ require 'yaml'
3
+
4
+ module Environment
5
+ # Color methods
6
+ def self.colorize(text, color_code)
7
+ "\e[#{color_code}m#{text}\e[0m"
8
+ end
9
+
10
+ def self.green(text)
11
+ colorize(text, 32)
12
+ end
13
+
14
+ def self.red(text)
15
+ colorize(text, 31)
16
+ end
17
+
18
+ def self.yellow(text)
19
+ colorize(text, 33)
20
+ end
21
+
22
+ def self.blue(text)
23
+ colorize(text, 34)
24
+ end
25
+
26
+ def self.magenta(text)
27
+ colorize(text, 35)
28
+ end
29
+
30
+ def self.cyan(text)
31
+ colorize(text, 36)
32
+ end
33
+
34
+ def self.bold(text)
35
+ colorize(text, 1)
36
+ end
37
+
38
+ # Environment-specific colors
39
+ def self.environment_color
40
+ case current
41
+ when 'development' then cyan(current)
42
+ when 'test' then green(current) # Lime/Green for test
43
+ when 'production' then red(current)
44
+ else yellow(current)
45
+ end
46
+ end
47
+
48
+ def self.load_config
49
+ env_file = File.expand_path('../../../env.yml', __dir__)
50
+ if File.exist?(env_file)
51
+ YAML.load_file(env_file)
52
+ else
53
+ {}
54
+ end
55
+ end
56
+
57
+ def self.current
58
+ ENV['APP_ENV'] || 'development'
59
+ end
60
+
61
+ def self.config
62
+ @config ||= load_config
63
+ @config[self.current] || {}
64
+ end
65
+
66
+ def self.database_url
67
+ db_config = config
68
+ if db_config['DB_SOCKET']
69
+ "mysql2://#{db_config['DB_USERNAME']}:#{db_config['DB_PASSWORD']}@#{db_config['DB_HOST']}#{db_config['DB_SOCKET']}/#{db_config['DB_DATABASE']}"
70
+ else
71
+ "mysql2://#{db_config['DB_USERNAME']}:#{db_config['DB_PASSWORD']}@#{db_config['DB_HOST']}:#{db_config['DB_PORT']}/#{db_config['DB_DATABASE']}"
72
+ end
73
+ end
74
+
75
+ def self.development?
76
+ current == 'development'
77
+ end
78
+
79
+ def self.production?
80
+ current == 'production'
81
+ end
82
+
83
+ def self.test?
84
+ current == 'test'
85
+ end
86
+ end
@@ -0,0 +1,80 @@
1
+ # infra/config/error_config.rb
2
+
3
+ module ErrorConfig
4
+
5
+ CUSTOM_ERROR_TEMPLATES = {
6
+ 404 => '', # web-app/display/ add this: pages/errors/404.hyr
7
+ 500 => '', # pages/errors/500.hyr
8
+ 422 => '', # pages/errors/422.hyr
9
+ 401 => '', # pages/errors/401.hyr
10
+ 403 => '' # pages/errors/403.hyr
11
+ }
12
+
13
+ CUSTOM_ERROR_LOCALS = {
14
+ 404 => ->(path, locals) {
15
+ {
16
+ path: path,
17
+ message: "The page you're looking for doesn't exist.",
18
+ suggestions: [
19
+ "Check the URL for typos",
20
+ "Go back to the homepage",
21
+ ]
22
+ }
23
+ },
24
+ 500 => ->(exception, locals) {
25
+ {
26
+ error: exception.message,
27
+ backtrace: exception.backtrace.first(5),
28
+ message: "Something went wrong on our end."
29
+ }
30
+ },
31
+ 422 => ->(exception, locals) {
32
+ {
33
+ error: exception.message,
34
+ message: "We couldn't process your request."
35
+ }
36
+ }
37
+ }
38
+
39
+ # Check if custom template exists for a status code
40
+ def self.custom_template_exists?(status)
41
+ template_path = CUSTOM_ERROR_TEMPLATES[status]
42
+ return false unless template_path
43
+
44
+ begin
45
+ template_file = find_template_anywhere(template_path)
46
+ File.exist?(template_file)
47
+ rescue
48
+ false
49
+ end
50
+ end
51
+
52
+ # Get custom template path for status code
53
+ def self.custom_template_for(status)
54
+ CUSTOM_ERROR_TEMPLATES[status]
55
+ end
56
+
57
+ # Get custom locals for status code
58
+ def self.custom_locals_for(status, *args)
59
+ return {} unless CUSTOM_ERROR_LOCALS[status]
60
+
61
+ CUSTOM_ERROR_LOCALS[status].call(*args)
62
+ end
63
+
64
+ # Helper method to find templates (delegates to WebAdapter)
65
+ def self.find_template_anywhere(template_name)
66
+ # This will be set by WebAdapter
67
+ if defined?(@template_finder)
68
+ @template_finder.call(template_name)
69
+ else
70
+ # Fallback for when not called from WebAdapter
71
+ search_pattern = File.join(ROOT, 'adapter-intake', '*', 'display', '**', "#{template_name.gsub(/\.hyr$/, '')}.hyr")
72
+ Dir.glob(search_pattern).first
73
+ end
74
+ end
75
+
76
+ # Set template finder from WebAdapter
77
+ def self.set_template_finder(finder)
78
+ @template_finder = finder
79
+ end
80
+ end
@@ -0,0 +1,2 @@
1
+ # infra/config/routes/api_routes.rb
2
+
@@ -0,0 +1,10 @@
1
+ # infra/config/routes/web_routes.rb
2
+
3
+ require_root 'adapter-intake/web-app/request/home_web_adapter'
4
+
5
+
6
+
7
+
8
+ Web = WebRouter.draw do
9
+ GET '/', to: [HomeWebAdapter, :home_page]
10
+ end
@@ -0,0 +1,62 @@
1
+ # infra/database/sequel_connection.rb
2
+ require 'sequel'
3
+ require 'yaml'
4
+ require_relative '../config/environment'
5
+
6
+ class SequelConnection
7
+ class << self
8
+ # Public method
9
+ def db
10
+ @db ||= connect
11
+ end
12
+
13
+ private
14
+
15
+ # Keep connect private
16
+ def connect
17
+ env = Environment.current
18
+
19
+ config_path = File.expand_path('../../env.yml', __dir__)
20
+ raise "env.yml not found at #{config_path}" unless File.exist?(config_path)
21
+
22
+ full_config = YAML.load_file(config_path)
23
+ db_config = full_config[env] || {}
24
+
25
+ adapter_map = {
26
+ 'pgsql' => 'postgres',
27
+ 'postgres' => 'postgres',
28
+ 'postgresql' => 'postgres',
29
+ 'mysql' => 'mysql2',
30
+ 'sqlite' => 'sqlite'
31
+ }
32
+
33
+ adapter_name = adapter_map[db_config['DB_CONNECTION']]
34
+ raise "Unsupported DB_CONNECTION: #{db_config['DB_CONNECTION']}" unless adapter_name
35
+
36
+ required_keys = %w[DB_CONNECTION DB_HOST DB_DATABASE DB_USERNAME DB_PASSWORD DB_PORT]
37
+ missing_keys = required_keys.select { |k| db_config[k].nil? || db_config[k].to_s.strip.empty? }
38
+ raise "Missing DB configuration keys: #{missing_keys.join(', ')}" if missing_keys.any?
39
+
40
+ # Build connection options
41
+ connection_options = {
42
+ adapter: adapter_name,
43
+ host: db_config['DB_HOST'],
44
+ database: db_config['DB_DATABASE'],
45
+ user: db_config['DB_USERNAME'],
46
+ password: db_config['DB_PASSWORD'],
47
+ port: db_config['DB_PORT']
48
+ }
49
+
50
+ # Add socket for MySQL if specified for linux
51
+ if db_config['DB_SOCKET'] && adapter_name == 'mysql2'
52
+ connection_options[:socket] = db_config['DB_SOCKET']
53
+ # add this to env.yml: DB_SOCKET: /opt/lampp/var/mysql/mysql.sock
54
+ end
55
+
56
+ Sequel.connect(connection_options)
57
+ rescue => e
58
+ puts "DB Connection failed: #{e.message}"
59
+ raise e
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,7 @@
1
+ # infra/gems/database.rb
2
+
3
+
4
+ # require 'pg'
5
+
6
+ # require 'mysql2'
7
+
@@ -0,0 +1,4 @@
1
+ # infra/gems/load_all.rb
2
+ require_relative 'web'
3
+ require_relative 'database'
4
+ require_relative 'utilities'
@@ -0,0 +1 @@
1
+ # infra/gems/utilities.rb
@@ -0,0 +1,3 @@
1
+ # infra/gems/web.rb
2
+ require 'rack'
3
+ require 'dotenv/load'
@@ -0,0 +1,13 @@
1
+ # server/api-server.ru
2
+ require_relative './../../boot'
3
+ require 'hyraft/server'
4
+ # Import the CORS middleware
5
+ require_relative '../../framework/middleware/cors_middleware'
6
+
7
+ use CorsMiddleware
8
+ use ApiLogger
9
+
10
+
11
+ app = ServerApiAdapter.new
12
+
13
+ run app
@@ -0,0 +1,32 @@
1
+ # infra/server/web-server.ru
2
+ require_relative './../../boot'
3
+ require 'hyraft/server'
4
+
5
+ public_path = File.expand_path("../../public", __dir__)
6
+ root_path = File.expand_path("../..", __dir__)
7
+
8
+ # Preload everything
9
+
10
+ # HyraftPreloader.preload_templates
11
+
12
+ # HyraftAssetPreloader.preload_assets(public_path)
13
+
14
+ # Serve node_modules FIRST
15
+ use Rack::Static, {
16
+ urls: ["/node_modules"],
17
+ root: root_path,
18
+ index: 'index.html'
19
+ }
20
+
21
+ # Then serve public assets
22
+ use Rack::Static, {
23
+ urls: ["/styles", "/css", "/images", "/js", "/icons", "/favicon.ico"], # You can add files like robot.txt
24
+ root: public_path,
25
+ index: 'index.html'
26
+ }
27
+
28
+ use WebLogger
29
+ use Rack::MethodOverride
30
+
31
+ run ServerWebAdapter.new
32
+
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "hyraft-framework",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "dependencies": {
7
+
8
+ }
9
+ }
Binary file
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- Uploaded to: ICON Repo, www.iconrepo.com, Generator: ICON Repo Mixer Tools -->
3
+ <svg fill="#000000" width="800px" height="800px" version="1.1" viewBox="144 144 512 512" xmlns="http://www.w3.org/2000/svg">
4
+ <g>
5
+ <path d="m517.61 242.56h-7.3984v-47.234c0-4.1758-1.6602-8.1797-4.6133-11.133-2.9492-2.9492-6.957-4.6094-11.133-4.6094h-236.16c-12.527 0-24.539 4.9766-33.398 13.832-8.8555 8.8594-13.832 20.875-13.832 33.398v251.91c0 5.625 3 10.824 7.8711 13.633 4.8711 2.8125 10.875 2.8125 15.746 0 4.8711-2.8086 7.8711-8.0078 7.8711-13.633v-207.51c5.0469 1.8359 10.371 2.793 15.742 2.8359h259.3c4.6094 0 8.3438 3.7344 8.3438 8.3438v298.19c0 4.6094-3.7344 8.3438-8.3438 8.3438h-266.7c-2.2148 0-4.3359-0.87891-5.8984-2.4414-1.5664-1.5664-2.4453-3.6875-2.4453-5.9023 0-5.625-3-10.82-7.8711-13.633s-10.875-2.8125-15.746 0-7.8711 8.0078-7.8711 13.633c0 10.566 4.1953 20.695 11.668 28.168 7.4688 7.4688 17.602 11.664 28.164 11.664h266.7c10.566 0 20.695-4.1953 28.168-11.664 7.4688-7.4727 11.664-17.602 11.664-28.168v-298.19c0-10.562-4.1953-20.695-11.664-28.164-7.4727-7.4727-17.602-11.668-28.168-11.668zm-275.05-15.746c0-4.1758 1.6562-8.1797 4.6094-11.133 2.9531-2.9492 6.957-4.6094 11.133-4.6094h220.42v31.488h-220.42c-4.1758 0-8.1797-1.6602-11.133-4.6133-2.9531-2.9531-4.6094-6.957-4.6094-11.133z"/>
6
+ <path d="m332.46 373.08c-2.957-2.9844-6.9805-4.6602-11.18-4.6602-4.1953 0-8.2227 1.6758-11.176 4.6602l-47.23 47.23h-0.003906c-2.9805 2.957-4.6562 6.9805-4.6562 11.18 0 4.1953 1.6758 8.2188 4.6562 11.176l47.234 47.234c2.9531 2.9805 6.9805 4.6562 11.176 4.6562 4.1992 0 8.2227-1.6758 11.18-4.6562 2.9805-2.957 4.6562-6.9805 4.6562-11.18s-1.6758-8.2227-4.6562-11.18l-36.211-36.051 36.211-36.055c2.9805-2.957 4.6562-6.9805 4.6562-11.18 0-4.1992-1.6758-8.2227-4.6562-11.176z"/>
7
+ <path d="m436.05 489.9c2.957 2.9805 6.9805 4.6562 11.18 4.6562s8.2227-1.6758 11.18-4.6562l47.23-47.23v-0.003907c2.9805-2.957 4.6562-6.9805 4.6562-11.176 0-4.1992-1.6758-8.2227-4.6562-11.18l-47.23-47.23c-3.9961-3.9961-9.8164-5.5547-15.27-4.0938-5.457 1.4609-9.7188 5.7227-11.18 11.18-1.4609 5.4531 0.097656 11.273 4.0898 15.27l36.215 36.055-36.211 36.055-0.003907-0.003907c-2.9805 2.957-4.6562 6.9805-4.6562 11.18s1.6758 8.2227 4.6562 11.18z"/>
8
+ <path d="m368.51 510.21c3.5938 0.10547 7.1172-1.0273 9.9844-3.2031 2.8633-2.1758 4.8945-5.2695 5.7578-8.7617l31.488-125.95c1.1328-4.1836 0.49219-8.6484-1.7734-12.34-2.2656-3.6953-5.9492-6.293-10.191-7.1836-4.0508-1-8.332-0.34766-11.902 1.8047-3.5742 2.1562-6.1445 5.6406-7.1484 9.6875l-31.488 125.95c-1.293 4.1797-0.78906 8.7109 1.3906 12.504 2.1797 3.793 5.8398 6.5078 10.102 7.4922 1.2578 0.15234 2.5234 0.15234 3.7812 0z"/>
9
+ </g>
10
+ </svg>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
3
+ <svg fill="#000000" width="800px" height="800px" version="1.1" viewBox="144 144 512 512" xmlns="http://www.w3.org/2000/svg">
4
+ <g>
5
+ <path d="m557.36 475.77 16.352-171.68c0.007812-0.070312-0.070313-0.078125-0.078126-0.14062 0.054688-0.39453 0.16406-0.76953 0.16406-1.1641 0-26.316-117.11-29.156-167.45-29.156-50.34 0-167.43 2.8438-167.43 29.156 0 0.41016 0.10938 0.78906 0.16406 1.1719 0 0.070312-0.085937 0.0625-0.078125 0.13281l16.336 171.68c-47.027 17.949-72.887 43.004-72.887 70.957 0 53.457 98.344 95.34 223.89 95.34 125.55 0 223.89-41.879 223.89-95.34 0.007812-27.957-25.852-53.016-72.871-70.957zm-17.285 15.398c-4.1797 13.609-53.449 32.898-133.74 32.898-80.375 0-129.67-19.332-133.73-32.953l-16.492-173.35c34.402 12.523 111.76 14.199 150.22 14.199 38.461 0 115.84-1.6758 150.25-14.199zm-133.73 48.641c49.594 0 103.85-7.8633 131.46-24.734l-1.582 16.586c-3.9531 13.648-51.852 33.047-129.88 33.047-77.988 0-125.91-19.398-129.87-33.055l-1.5898-16.672c27.582 16.918 81.82 24.828 131.46 24.828zm0-250.44c77.422 0 130.52 7.1094 147.48 13.422-16.957 6.3125-70.047 13.43-147.48 13.43-77.414 0-130.5-7.1172-147.45-13.43 16.953-6.3047 70.043-13.422 147.45-13.422zm0 336.96c-124.5 0-208.14-41.164-208.14-79.594 0-19.973 21.262-39.621 58.695-54.672l3.9688 41.707c0.03125 0.33984 0.085938 0.67578 0.16406 1.0078 7.1797 31.395 80.367 45.695 145.32 45.695 64.984 0 138.18-14.297 145.33-45.703 0.070312-0.33203 0.125-0.66016 0.16406-1l3.9688-41.707c37.422 15.043 58.688 34.691 58.688 54.672-0.007812 38.43-83.648 79.594-208.16 79.594z"/>
6
+ <path d="m630.48 189.23h-388.65c-7.4961 0-13.586 6.0781-13.586 13.562v29.961c0 7.4688 6.0938 13.555 13.586 13.555h388.65c7.4688 0 13.555-6.0781 13.555-13.555l0.003906-29.969c0-7.4805-6.0781-13.555-13.555-13.555zm-64.363 15.742v25.586h-259.95v-25.586zm-322.12 0h46.43v25.586h-46.43zm384.3 25.586h-46.43v-25.586h46.43z"/>
7
+ <path d="m205.11 217.77c0-4.3516-3.5273-7.8711-7.8711-7.8711h-33.402c-4.3438 0-7.8711 3.5195-7.8711 7.8711 0 4.3516 3.5273 7.8711 7.8711 7.8711h33.402c4.3477 0 7.8711-3.5273 7.8711-7.8711z"/>
8
+ <path d="m192.17 193.34c1.4805 1.2422 3.2812 1.8516 5.0703 1.8516 2.2422 0 4.4648-0.95312 6.0234-2.793 2.8008-3.3203 2.3789-8.2891-0.94531-11.09l-25.535-21.535c-3.332-2.8125-8.3008-2.3711-11.102 0.94141-2.8008 3.3203-2.3789 8.2891 0.94531 11.09z"/>
9
+ <path d="m202.32 254.2c3.3203-2.8008 3.7461-7.7695 0.9375-11.09-2.8008-3.3281-7.7617-3.7539-11.09-0.94531l-25.535 21.547c-3.3203 2.8008-3.7461 7.7695-0.9375 11.09 1.5586 1.8438 3.7773 2.793 6.0234 2.793 1.793 0 3.5977-0.60547 5.0781-1.8516z"/>
10
+ <path d="m189.37 345.14v6.0625c0 4.3516 3.5273 7.8711 7.8711 7.8711s7.8711-3.5195 7.8711-7.8711v-6.0625h6.0625c4.3438 0 7.8711-3.5195 7.8711-7.8711s-3.5273-7.8711-7.8711-7.8711h-6.0625v-6.0312c0-4.3516-3.5273-7.8711-7.8711-7.8711s-7.8711 3.5195-7.8711 7.8711v6.0312h-6.0234c-4.3438 0-7.8711 3.5195-7.8711 7.8711s3.5273 7.8711 7.8711 7.8711z"/>
11
+ <path d="m323.91 400.15h-6.0312v-6.0312c0-4.3516-3.5273-7.8711-7.8711-7.8711s-7.8711 3.5195-7.8711 7.8711v6.0312h-6.0625c-4.3438 0-7.8711 3.5195-7.8711 7.8711 0 4.3516 3.5273 7.8711 7.8711 7.8711h6.0625v6.0625c0 4.3516 3.5273 7.8711 7.8711 7.8711s7.8711-3.5195 7.8711-7.8711v-6.0625h6.0312c4.3438 0 7.8711-3.5195 7.8711-7.8711 0.003906-4.3516-3.5234-7.8711-7.8711-7.8711z"/>
12
+ </g>
13
+ </svg>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- Uploaded to: ICON Repo, www.iconrepo.com, Generator: ICON Repo Mixer Tools -->
3
+ <svg fill="#000000" width="800px" height="800px" version="1.1" viewBox="144 144 512 512" xmlns="http://www.w3.org/2000/svg">
4
+ <g fill-rule="evenodd">
5
+ <path d="m400 557.44c-11.594 0-20.992 9.3984-20.992 20.992s9.3984 20.992 20.992 20.992 20.992-9.3984 20.992-20.992-9.3984-20.992-20.992-20.992zm-41.984 20.992c0-23.188 18.797-41.984 41.984-41.984s41.984 18.797 41.984 41.984-18.797 41.984-41.984 41.984-41.984-18.797-41.984-41.984z"/>
6
+ <path d="m400 200.57c-11.594 0-20.992 9.3984-20.992 20.992s9.3984 20.992 20.992 20.992 20.992-9.3984 20.992-20.992-9.3984-20.992-20.992-20.992zm-41.984 20.992c0-23.188 18.797-41.984 41.984-41.984s41.984 18.797 41.984 41.984-18.797 41.984-41.984 41.984-41.984-18.797-41.984-41.984z"/>
7
+ <path d="m504.96 326.53c-11.594 0-20.992 9.3984-20.992 20.992s9.3984 20.992 20.992 20.992c11.598 0 20.992-9.3984 20.992-20.992s-9.3945-20.992-20.992-20.992zm-41.98 20.992c0-23.188 18.793-41.984 41.98-41.984 23.191 0 41.984 18.797 41.984 41.984s-18.793 41.984-41.984 41.984c-23.188 0-41.98-18.797-41.98-41.984z"/>
8
+ <path d="m410.5 253.05v293.89h-20.992v-293.89z"/>
9
+ <path d="m515.45 379.01v41.984c0 28.98-23.496 52.48-52.477 52.48h-62.977v-20.992h62.977c17.387 0 31.484-14.102 31.484-31.488v-41.984z"/>
10
+ <path d="m295.04 295.04c11.594 0 20.992 9.3984 20.992 20.992s-9.3984 20.992-20.992 20.992-20.992-9.3984-20.992-20.992 9.3984-20.992 20.992-20.992zm41.984 20.992c0-23.188-18.797-41.984-41.984-41.984s-41.984 18.797-41.984 41.984 18.797 41.984 41.984 41.984 41.984-18.797 41.984-41.984z"/>
11
+ <path d="m284.54 347.52v41.984c0 28.98 23.496 52.48 52.48 52.48h62.977v-20.992h-62.977c-17.391 0-31.488-14.102-31.488-31.488v-41.984z"/>
12
+ </g>
13
+ </svg>
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- Uploaded to: ICON Repo, www.iconrepo.com, Generator: ICON Repo Mixer Tools -->
3
+ <svg fill="#000000" width="800px" height="800px" version="1.1" viewBox="144 144 512 512" xmlns="http://www.w3.org/2000/svg">
4
+ <g>
5
+ <path d="m583.89 598.32v4.3516h31.371v-126h-31.371z"/>
6
+ <path d="m500.39 562.91c6.1719 0.011719 12.098-2.4297 16.469-6.7891 4.375-4.3594 6.8359-10.277 6.8438-16.449 0.007813-6.1719-2.4375-12.098-6.8008-16.465-4.3594-4.3711-10.277-6.8281-16.449-6.832-6.1758-0.003906-12.098 2.4453-16.465 6.8086-4.3672 4.3633-6.8203 10.285-6.8203 16.457 0.011719 6.1602 2.4609 12.062 6.8125 16.422s10.25 6.8203 16.41 6.8477z"/>
7
+ <path d="m334.46 268.32 29.449 70.992h72.184l29.449-70.992-15.48-37.281h-100.12z"/>
8
+ <path d="m216.11 476.67h-31.375v126h31.375z"/>
9
+ <path d="m400 562.91c6.1719 0.011719 12.098-2.4297 16.469-6.7891 4.375-4.3594 6.8359-10.277 6.8438-16.449s-2.4375-12.098-6.8008-16.465c-4.3594-4.3711-10.277-6.8281-16.453-6.832-6.1719-0.003906-12.094 2.4453-16.461 6.8086-4.3672 4.3633-6.8203 10.285-6.8203 16.457 0.011718 6.1602 2.4609 12.062 6.8125 16.422 4.3516 4.3594 10.25 6.8203 16.41 6.8477z"/>
10
+ <path d="m363.91 197.33-10.168 24.551h92.52l-10.168-24.551z"/>
11
+ <path d="m299.56 562.91c6.1719 0.011719 12.098-2.4297 16.469-6.7891 4.375-4.3594 6.8359-10.277 6.8438-16.449 0.007812-6.1719-2.4375-12.098-6.8008-16.465-4.3594-4.3711-10.277-6.8281-16.453-6.832-6.1719-0.003906-12.094 2.4453-16.461 6.8086s-6.8203 10.285-6.8203 16.457c0.011718 6.1602 2.4609 12.062 6.8125 16.422 4.3516 4.3594 10.25 6.8203 16.41 6.8477z"/>
12
+ <path d="m225.27 593.73h349.46v-108.13h-349.46zm275.12-86.469c8.6055-0.011719 16.863 3.3945 22.953 9.4727 6.0898 6.082 9.5156 14.332 9.5195 22.938 0.003906 8.6055-3.4141 16.859-9.5 22.945-6.082 6.0859-14.336 9.5-22.941 9.4961-8.6055-0.003907-16.859-3.4258-22.938-9.5195-6.0781-6.0898-9.4883-14.348-9.4766-22.953 0.011719-8.582 3.4297-16.812 9.5-22.883 6.0703-6.0703 14.297-9.4844 22.883-9.4961zm-100.39 0c8.6055-0.011719 16.863 3.3945 22.953 9.4727 6.0898 6.082 9.5156 14.332 9.5195 22.938s-3.4141 16.859-9.5 22.945c-6.0859 6.0859-14.34 9.5-22.945 9.4961-8.6055-0.003907-16.855-3.4258-22.934-9.5195-6.0781-6.0898-9.4883-14.348-9.4766-22.953 0.023437-8.5781 3.4453-16.801 9.5117-22.871 6.0664-6.0664 14.289-9.4844 22.871-9.5078zm-100.39 0h-0.003907c8.6055 0 16.855 3.418 22.938 9.5 6.082 6.0859 9.4961 14.34 9.4922 22.941-0.003906 8.6016-3.4258 16.852-9.5156 22.93-6.0859 6.0781-14.34 9.4883-22.941 9.4805-8.6055-0.007813-16.852-3.4336-22.926-9.5234-6.0781-6.0898-9.4844-14.344-9.4727-22.949 0.011719-8.582 3.4297-16.812 9.4961-22.883 6.0703-6.0703 14.301-9.4844 22.887-9.4961z"/>
13
+ <path d="m429.08 412.55c3.2344-8.7305 2.3516-18.457-2.4062-26.461-4.7578-8.0039-12.879-13.43-22.098-14.758v-22.902h-9.1602v27.254c0 1.2148 0.48438 2.3789 1.3438 3.2383 0.85547 0.85938 2.0234 1.3398 3.2383 1.3398 7.082-0.11328 13.77 3.2695 17.879 9.043 4.1094 5.7734 5.1133 13.199 2.6836 19.859l-18.777-7.9219v-0.003906c-1.1484-0.45703-2.4258-0.45703-3.5742 0l-18.777 7.9258c-0.78516-2.2227-1.2031-4.5586-1.2344-6.918 0-2.5273-2.0508-4.5781-4.582-4.5781s-4.5781 2.0508-4.5781 4.5781c0.011719 3.5781 0.64453 7.1289 1.875 10.488l-145.64 61.008 17.312 2.7031 132.82-55.785h-0.003906c5.8203 7.7812 14.969 12.363 24.688 12.363s18.867-4.582 24.688-12.363l132.82 55.785 17.312-2.7031zm-29.082 11.312c-6.0117-0.015625-11.75-2.5195-15.848-6.9141l15.848-6.6875 15.848 6.6406h-0.003906c-4.0859 4.418-9.8281 6.9375-15.844 6.9609z"/>
14
+ </g>
15
+ </svg>
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- Uploaded to: ICON Repo, www.iconrepo.com, Generator: ICON Repo Mixer Tools -->
3
+ <svg fill="#000000" width="800px" height="800px" version="1.1" viewBox="144 144 512 512" xmlns="http://www.w3.org/2000/svg">
4
+ <g>
5
+ <path d="m602.71 578.82h-171.95c-3.9414 0-7.1133-3.1719-7.1133-7.1133 0-3.9414 3.1719-7.1133 7.1133-7.1133l171.95 0.003906c5.8984 0 10.668-4.7695 10.668-10.668v-342.36c0-5.8984-4.7695-10.668-10.668-10.668h-405.42c-5.8984 0-10.668 4.7695-10.668 10.668v342.35c0 5.8984 4.7695 10.668 10.668 10.668h171.95c3.9414 0 7.1133 3.1719 7.1133 7.1133 0 3.9414-3.1719 7.1133-7.1133 7.1133h-171.95c-13.723 0-24.895-11.172-24.895-24.895v-342.35c0-13.723 11.172-24.895 24.895-24.895h405.42c13.723 0 24.895 11.172 24.895 24.895v342.35c0 13.754-11.172 24.895-24.895 24.895z"/>
6
+ <path d="m620.49 263.59h-440.98c-3.9414 0-7.1133-3.1719-7.1133-7.1133s3.1719-7.1133 7.1133-7.1133h440.98c3.9414 0 7.1133 3.1719 7.1133 7.1133s-3.1719 7.1133-7.1133 7.1133z"/>
7
+ <path d="m580.45 232.26h-176.93c-3.9414 0-7.1133-3.1719-7.1133-7.1133 0-3.9414 3.1719-7.1133 7.1133-7.1133h176.93c3.9414 0 7.1133 3.1719 7.1133 7.1133-0.003906 3.9453-3.2031 7.1133-7.1133 7.1133z"/>
8
+ <path d="m234.93 225.15c0 5.1719-4.1914 9.3633-9.3633 9.3633s-9.3672-4.1914-9.3672-9.3633c0-5.1719 4.1953-9.3672 9.3672-9.3672s9.3633 4.1953 9.3633 9.3672"/>
9
+ <path d="m274.14 225.15c0 5.1719-4.1953 9.3633-9.3672 9.3633s-9.3633-4.1914-9.3633-9.3633c0-5.1719 4.1914-9.3672 9.3633-9.3672s9.3672 4.1953 9.3672 9.3672"/>
10
+ <path d="m305.48 215.9c5.1055 0.82812 8.5742 5.6406 7.7461 10.746-0.82812 5.1055-5.6406 8.5703-10.746 7.7422s-8.5703-5.6406-7.7422-10.746 5.6367-8.5703 10.742-7.7422"/>
11
+ <path d="m495.81 312.34h-88.348c-3.9414 0-7.1133-3.1719-7.1133-7.1133s3.1719-7.1133 7.1133-7.1133h88.344c3.9414 0 7.1133 3.1719 7.1133 7.1133 0.003906 3.9414-3.1992 7.1133-7.1094 7.1133z"/>
12
+ <path d="m573.28 312.34h-54.945c-3.9414 0-7.1133-3.1719-7.1133-7.1133s3.1719-7.1133 7.1133-7.1133h54.945c3.9414 0 7.1133 3.1719 7.1133 7.1133-0.003906 3.9414-3.1719 7.1133-7.1133 7.1133z"/>
13
+ <path d="m573.28 344.7h-99.488c-3.9414 0-7.1133-3.1719-7.1133-7.1133 0-3.9414 3.1719-7.1133 7.1133-7.1133h99.488c3.9414 0 7.1133 3.1719 7.1133 7.1133-0.003906 3.9414-3.1719 7.1133-7.1133 7.1133z"/>
14
+ <path d="m451.62 344.7h-44.156c-3.9414 0-7.1133-3.1719-7.1133-7.1133 0-3.9414 3.1719-7.1133 7.1133-7.1133h44.156c3.9414 0 7.1133 3.1719 7.1133 7.1133 0 3.9414-3.1719 7.1133-7.1133 7.1133z"/>
15
+ <path d="m482.92 377.09h-75.453c-3.9414 0-7.1133-3.1719-7.1133-7.1133 0-3.9414 3.1719-7.1133 7.1133-7.1133h75.453c3.9414 0 7.1133 3.1719 7.1133 7.1133 0 3.9414-3.1719 7.1133-7.1133 7.1133z"/>
16
+ <path d="m573.28 377.09h-68.191c-3.9414 0-7.1133-3.1719-7.1133-7.1133 0-3.9414 3.1719-7.1133 7.1133-7.1133h68.191c3.9414 0 7.1133 3.1719 7.1133 7.1133-0.003906 3.9414-3.1719 7.1133-7.1133 7.1133z"/>
17
+ <path d="m260.68 370.66c-1.5117 0-3.0234-0.47266-4.2969-1.4531l-33.961-25.961c-1.75-1.332-2.7852-3.4375-2.7852-5.6602 0-2.2227 1.0391-4.2969 2.7852-5.6602l33.961-25.961c3.1133-2.3711 7.5859-1.7773 9.957 1.332 2.3711 3.1133 1.7773 7.5859-1.332 9.957l-26.582 20.301 26.582 20.301c3.1133 2.3711 3.7344 6.8477 1.332 9.957-1.3906 1.8672-3.5273 2.8477-5.6602 2.8477z"/>
18
+ <path d="m333.44 370.66c-2.1328 0-4.2656-0.94922-5.6602-2.7852-2.3711-3.1133-1.7773-7.5859 1.332-9.957l26.582-20.301-26.582-20.301c-3.1133-2.3711-3.7344-6.8477-1.332-9.957 2.3711-3.1133 6.8477-3.7344 9.957-1.332l33.992 25.961c1.75 1.332 2.7852 3.4375 2.7852 5.6602 0 2.2227-1.0391 4.2969-2.7852 5.6602l-33.992 25.961c-1.2734 0.91406-2.8164 1.3906-4.2969 1.3906z"/>
19
+ <path d="m285.96 384.44c-0.62109 0-1.2734-0.089844-1.9258-0.26562-3.793-1.0664-5.9883-4.9805-4.9492-8.7734l22.227-79.453c1.0664-3.793 4.9805-5.9883 8.7734-4.9492 3.793 1.0664 5.9883 4.9805 4.9492 8.7734l-22.195 79.453c-0.92188 3.1367-3.7695 5.2148-6.8789 5.2148z"/>
20
+ <path d="m400 613.32c-2.0156 0-3.9727-0.85938-5.3047-2.3711l-121.12-135.76c-2.6094-2.9336-2.3711-7.4375 0.5625-10.047 2.9336-2.6094 7.4375-2.3711 10.047 0.5625l115.82 129.8 115.82-129.84c2.6094-2.9336 7.1133-3.1992 10.047-0.5625 2.9336 2.6094 3.1992 7.1133 0.5625 10.047l-121.12 135.76c-1.3359 1.543-3.2891 2.4023-5.3047 2.4023z"/>
21
+ <path d="m400 613.32c-2.9922 0-5.6602-1.8672-6.668-4.6836l-49.254-134.93-36.48-53.641c-2.2227-3.2617-1.3633-7.6758 1.8672-9.8672 3.2617-2.2227 7.6758-1.3633 9.8672 1.8672l36.957 54.352c0.32422 0.47266 0.59375 1.0078 0.80078 1.5703l42.91 117.48 42.883-117.48c0.20703-0.5625 0.47266-1.0664 0.80078-1.5703l36.957-54.352c2.2227-3.2617 6.6367-4.0898 9.8672-1.8672 3.2617 2.2227 4.0898 6.6367 1.8672 9.8672l-36.48 53.609-49.227 134.96c-1.0078 2.8125-3.6758 4.6797-6.668 4.6797z"/>
22
+ <path d="m521.12 477.55h-242.25c-3.9414 0-7.1133-3.1719-7.1133-7.1133s3.1719-7.1133 7.1133-7.1133h242.24c3.9414 0 7.1133 3.1719 7.1133 7.1133 0.003906 3.9414-3.1992 7.1133-7.1094 7.1133z"/>
23
+ <path d="m521.12 477.55h-242.25c-2.6094 0-4.9805-1.4219-6.2227-3.7031-1.2461-2.2812-1.1562-5.0391 0.23828-7.2305l34.613-54.352c1.3047-2.043 3.5547-3.2891 5.9883-3.2891l173.04-0.003907c2.4297 0 4.6836 1.2461 5.9883 3.2891l34.613 54.352c1.3945 2.1914 1.4805 4.9805 0.23828 7.2305-1.2461 2.2539-3.6758 3.707-6.2539 3.707zm-229.29-14.223h216.34l-25.547-40.125-165.25-0.003906z"/>
24
+ <path d="m449.55 477.55h-99.102c-2.8164 0-5.3633-1.6602-6.5195-4.2383s-0.65234-5.5703 1.2461-7.6758l49.551-54.352c1.332-1.4805 3.2617-2.3125 5.2461-2.3125s3.9102 0.82813 5.2461 2.3125l49.551 54.352c1.8984 2.0742 2.4023 5.0977 1.2461 7.6758-1.1602 2.5781-3.6523 4.2383-6.4648 4.2383zm-82.98-14.223h66.887l-33.457-36.691z"/>
25
+ </g>
26
+ </svg>
@@ -0,0 +1,22 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <link rel="icon" type="image/x-icon" href="/favicon.ico">
7
+
8
+ <!-- Bootstrap CSS -->
9
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
10
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
11
+
12
+ <hyraft meta="tags">
13
+
14
+ <hyraft styles="css">
15
+ </head>
16
+
17
+ <body>
18
+
19
+ <hyraft content="hyraft">
20
+ <hyraft script="javascript">
21
+ </body>
22
+ </html>