shopify_theme_builder 0.3.0 → 0.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 307e28c3c750b87460a048c082ba3c3287a480419c1b1c52faa84660de8b543a
4
- data.tar.gz: 1ea87aa101f2858f46090e8f12d61c231bb4671dbd10aaa53b5427497690ae28
3
+ metadata.gz: 96de2b7ebf1688b16c967eb0a10fc193b0ba49064f0612a2a8ae7b73d8ff5ca4
4
+ data.tar.gz: e8db2e1b3643c1f2b479a4e87c03c00e1c2c8e3354ec7914dca566eabab82746
5
5
  SHA512:
6
- metadata.gz: 4997036e87e815574d49b2857e4c8f859fcd53afcd279652ec3b81b563d454bd0826c21101a616c82cb8b0b570817e1c3d6d20a827c7d91d0940f81ed5d4766c
7
- data.tar.gz: 199222a677430c7ec42719ef04574050327f61f8648c5096b7d60c9f06ac9a4c03b42fdbc90e307f41b46fd916eebb79fbac437a82c67ba00f87ce3805126279
6
+ metadata.gz: 1bbc6a322bd5a4bb4156e5692c49fa7358b962da211453289a9e9ad7bb419d76b0e28508b4fa41ec6f6eb662436d3b79c16d4e5a6a2ae46d130cb79b9faae1b4
7
+ data.tar.gz: ce8c3198cc5d190ca41d7e1e46f69a3c59fa3649735d74c11bcc42c37eefb950723484453e6fd909785273323c257cab39711eafbb4a5bec9da3e19d47be3ec1
data/README.md CHANGED
@@ -33,6 +33,11 @@ _components/
33
33
  schema.json
34
34
  style.css
35
35
  index.js
36
+ controllers.js
37
+ assets/
38
+ tailwind-output.css
39
+ tailwind.css
40
+ controllers.js
36
41
  blocks/
37
42
  button.liquid
38
43
  ```
@@ -43,6 +48,34 @@ All files inside the `button` folder will be compiled into a single `button.liqu
43
48
 
44
49
  ShopifyThemeBuilder also supports Tailwind CSS integration. You can specify an input CSS file that includes Tailwind directives and an output CSS file where the compiled styles will be saved. The watcher will automatically run the Tailwind build process whenever changes are detected in the components folder.
45
50
 
51
+ ## Stimulus JS Support
52
+
53
+ ShopifyThemeBuilder supports Stimulus JS integration. You can specify an output JavaScript file where the compiled Stimulus controllers will be saved. The watcher will automatically compile the Stimulus controllers whenever changes are detected in the components folder.
54
+
55
+ ### How to create Stimulus controllers
56
+
57
+ To create Stimulus controllers, create a `controller.js` file inside your component folder. For example:
58
+
59
+ ```
60
+ _components/
61
+ my_component/
62
+ controller.js
63
+ ```
64
+
65
+ The content of the `controller.js` file should follow the Stimulus controller structure. For example:
66
+
67
+ ```javascript
68
+ class HelloController extends Controller {
69
+ connect() {
70
+ console.log("My component controller connected")
71
+ }
72
+ }
73
+
74
+ Stimulus.register("hello", HelloController)
75
+ ```
76
+
77
+ When the watcher runs, it will compile all `controller.js` files from your components into a single JavaScript file that can be included in your Shopify theme.
78
+
46
79
  ## Installation
47
80
 
48
81
  Install the gem and add to the application's Gemfile by executing:
@@ -61,9 +94,10 @@ bundle exec theme-builder watch
61
94
 
62
95
  You can customize multiple options when running the watcher:
63
96
  - `--folders`: Specify one or more folders to watch (default is `_components`).
64
- - `--tailwind-input-file`: Specify the Tailwind CSS input file (default is `src/styles/tailwind.css`).
65
- - `--tailwind-output-file`: Specify the Tailwind CSS output file (default is `assets/tailwind-output.css`).
97
+ - `--tailwind-input-file`: Specify the Tailwind CSS input file (default is `./assets/tailwind.css`).
98
+ - `--tailwind-output-file`: Specify the Tailwind CSS output file (default is `./assets/tailwind-output.css`).
66
99
  - `--skip-tailwind`: Skip the Tailwind CSS build process (default is `false`).
100
+ - `--stimulus-output-file`: Specify the Stimulus JS output file (default is `./assets/controllers.js`).
67
101
 
68
102
  If you need help with all available options, or how to set them, run:
69
103
 
@@ -79,6 +113,12 @@ The watcher will create a CSS file that can be included in your Shopify theme la
79
113
  {{ 'tailwind-output.css' | asset_url | stylesheet_tag }}
80
114
  ```
81
115
 
116
+ And a JavaScript file that can be included in your Shopify theme layout in this way:
117
+
118
+ ```liquid
119
+ <script type="module" src="{{ 'controllers.js' | asset_url }}"></script>
120
+ ```
121
+
82
122
  ## Development
83
123
 
84
124
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -88,7 +128,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
88
128
  ## Next Steps
89
129
 
90
130
  - [x] Run the tailwind build process automatically.
91
- - [ ] Add Stimulus JS support.
131
+ - [x] Add Stimulus JS support.
92
132
  - [ ] Create a command to build an example component with all the files.
93
133
  - [ ] Decompile existing Shopify files into components structure (?).
94
134
 
@@ -11,12 +11,15 @@ module ShopifyThemeBuilder
11
11
  method_option :tailwind_output_file, type: :string, default: "./assets/tailwind-output.css",
12
12
  desc: "Tailwind CSS output file"
13
13
  method_option :skip_tailwind, type: :boolean, default: false, desc: "Skip Tailwind CSS processing"
14
+ method_option :stimulus_output_file, type: :string, default: "./assets/controllers.js",
15
+ desc: "Stimulus controllers output file"
14
16
  def watch
15
17
  ShopifyThemeBuilder.watch(
16
18
  folders_to_watch: options[:folders],
17
19
  tailwind_input_file: options[:tailwind_input_file],
18
20
  tailwind_output_file: options[:tailwind_output_file],
19
- skip_tailwind: options[:skip_tailwind]
21
+ skip_tailwind: options[:skip_tailwind],
22
+ stimulus_output_file: options[:stimulus_output_file]
20
23
  )
21
24
  end
22
25
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "filewatcher"
4
+
5
+ module ShopifyThemeBuilder
6
+ # It wraps the Filewatcher functionality to monitor file changes.
7
+ # It delegates method calls to the underlying Filewatcher instance.
8
+ # Check: https://github.com/filewatcher/filewatcher
9
+ class Filewatcher
10
+ def initialize(...)
11
+ @filewatcher = ::Filewatcher.new(...)
12
+ end
13
+
14
+ def method_missing(name, ...)
15
+ if @filewatcher.respond_to?(name)
16
+ @filewatcher.send(name, ...)
17
+ else
18
+ super
19
+ end
20
+ end
21
+
22
+ def respond_to_missing?(name, include_private)
23
+ @filewatcher.respond_to?(name) || super
24
+ end
25
+ end
26
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "logger"
4
+
3
5
  module ShopifyThemeBuilder
4
6
  # LiquidProcessor is responsible for processing Liquid files
5
7
  # by combining various related files (Liquid, schema, CSS, JS, doc, comment)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ShopifyThemeBuilder
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -1,27 +1,125 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "filewatcher"
3
+ require "fileutils"
4
+ require "tailwindcss/ruby"
4
5
 
5
6
  module ShopifyThemeBuilder
6
- # Watcher class for ShopifyThemeBuilder.
7
- # It wraps the Filewatcher functionality to monitor file changes.
8
- # It delegates method calls to the underlying Filewatcher instance.
9
- # Check: https://github.com/filewatcher/filewatcher
7
+ # Watcher is responsible for monitoring specified folders for changes
8
+ # and triggering the build process for Shopify theme components.
10
9
  class Watcher
11
- def initialize(...)
12
- @filewatcher = Filewatcher.new(...)
10
+ def initialize(
11
+ folders_to_watch: ["_components"],
12
+ tailwind_input_file: "./assets/tailwind.css",
13
+ tailwind_output_file: "./assets/tailwind-output.css",
14
+ skip_tailwind: false,
15
+ stimulus_output_file: "./assets/controllers.js"
16
+ )
17
+ @folders_to_watch = folders_to_watch
18
+ @tailwind_input_file = tailwind_input_file
19
+ @tailwind_output_file = tailwind_output_file
20
+ @skip_tailwind = skip_tailwind
21
+ @stimulus_output_file = stimulus_output_file
13
22
  end
14
23
 
15
- def method_missing(name, ...)
16
- if @filewatcher.respond_to?(name)
17
- @filewatcher.send(name, ...)
18
- else
19
- super
24
+ def watch
25
+ create_folders
26
+
27
+ initial_build
28
+
29
+ create_tailwind_file
30
+
31
+ run_tailwind
32
+
33
+ run_stimulus
34
+
35
+ watch_folders
36
+ end
37
+
38
+ private
39
+
40
+ def create_folders
41
+ puts "Creating necessary folders..."
42
+
43
+ FileUtils.mkdir_p(@folders_to_watch)
44
+ FileUtils.mkdir_p("sections")
45
+ FileUtils.mkdir_p("blocks")
46
+ FileUtils.mkdir_p("snippets")
47
+ end
48
+
49
+ def initial_build
50
+ puts "Doing an initial build..."
51
+
52
+ @folders_to_watch.each do |folder|
53
+ Builder.new(files_to_process: Dir.glob("#{folder}/**/*.*")).build
54
+ end
55
+ end
56
+
57
+ def watch_folders
58
+ puts "Watching for changes in '#{@folders_to_watch.join(", ")}' folders..."
59
+
60
+ Filewatcher.new(@folders_to_watch).watch do |changes|
61
+ changes.each_key do |filename|
62
+ relative_filename = filename.gsub("#{Dir.pwd}/", "")
63
+
64
+ Builder.new(files_to_process: [relative_filename]).build if relative_filename.start_with?(*@folders_to_watch)
65
+ end
66
+
67
+ run_tailwind
68
+
69
+ run_stimulus if changes.keys.any? { |f| f.end_with?("controller.js") }
20
70
  end
21
71
  end
22
72
 
23
- def respond_to_missing?(name, include_private)
24
- @filewatcher.respond_to?(name) || super
73
+ def run_tailwind
74
+ return if @skip_tailwind
75
+
76
+ puts "Running Tailwind CSS build..."
77
+
78
+ system("tailwindcss", "-i", @tailwind_input_file, "-o", @tailwind_output_file)
79
+ end
80
+
81
+ def create_tailwind_file
82
+ return if @skip_tailwind || File.exist?(@tailwind_input_file)
83
+
84
+ puts "Creating default Tailwind CSS input file at '#{@tailwind_input_file}'..."
85
+
86
+ FileUtils.mkdir_p(File.dirname(@tailwind_input_file))
87
+ File.write @tailwind_input_file, tailwind_base_config
88
+ end
89
+
90
+ def tailwind_base_config
91
+ return '@import "tailwindcss";' if Gem::Version.new(Tailwindcss::Ruby::VERSION) >= Gem::Version.new("4.0.0")
92
+
93
+ system("tailwindcss", "init") unless File.exist?("tailwind.config.js")
94
+
95
+ <<~TAILWIND.strip
96
+ @tailwind base;
97
+ @tailwind components;
98
+ @tailwind utilities;
99
+ TAILWIND
100
+ end
101
+
102
+ def run_stimulus
103
+ controllers_files = @folders_to_watch.map { Dir.glob("#{_1}/**/controller.js") }.flatten
104
+
105
+ return if controllers_files.empty?
106
+
107
+ puts "Building Stimulus controllers..."
108
+
109
+ content = +base_stimulus_content
110
+
111
+ controllers_files.each do |file|
112
+ content << File.read(file)
113
+ content << "\n"
114
+ end
115
+
116
+ FileUtils.mkdir_p(File.dirname(@stimulus_output_file))
117
+ File.write(@stimulus_output_file, content.strip)
118
+ end
119
+
120
+ def base_stimulus_content
121
+ "import { Application, Controller } from \"https://unpkg.com/@hotwired/stimulus/dist/stimulus.js\"\n\
122
+ window.Stimulus = Application.start()\n\n"
25
123
  end
26
124
  end
27
125
  end
@@ -1,70 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "fileutils"
4
- require "logger"
5
3
  require_relative "shopify_theme_builder/version"
6
- require_relative "shopify_theme_builder/watcher"
4
+ require_relative "shopify_theme_builder/filewatcher"
7
5
  require_relative "shopify_theme_builder/liquid_processor"
8
6
  require_relative "shopify_theme_builder/builder"
9
7
  require_relative "shopify_theme_builder/command_line"
8
+ require_relative "shopify_theme_builder/watcher"
10
9
 
11
10
  # The main module for ShopifyThemeBuilder.
12
11
  module ShopifyThemeBuilder
13
- class << self
14
- def watch(
15
- folders_to_watch: ["_components"],
16
- tailwind_input_file: "./assets/tailwind.css",
17
- tailwind_output_file: "./assets/tailwind-output.css",
18
- skip_tailwind: false
19
- )
20
- create_folders(folders_to_watch)
21
-
22
- initial_build(folders_to_watch)
23
-
24
- run_tailwind(tailwind_input_file, tailwind_output_file) unless skip_tailwind
25
-
26
- watch_folders(folders_to_watch) do
27
- run_tailwind(tailwind_input_file, tailwind_output_file) unless skip_tailwind
28
- end
29
- end
30
-
31
- private
32
-
33
- def create_folders(folders_to_watch)
34
- puts "Creating necessary folders..."
35
-
36
- FileUtils.mkdir_p(folders_to_watch)
37
- FileUtils.mkdir_p("sections")
38
- FileUtils.mkdir_p("blocks")
39
- FileUtils.mkdir_p("snippets")
40
- end
41
-
42
- def initial_build(folders_to_watch)
43
- puts "Doing an initial build..."
44
-
45
- folders_to_watch.each do |folder|
46
- Builder.new(files_to_process: Dir.glob("#{folder}/**/*.*")).build
47
- end
48
- end
49
-
50
- def watch_folders(folders_to_watch)
51
- puts "Watching for changes in '#{folders_to_watch.join(", ")}' folders..."
52
-
53
- Watcher.new(folders_to_watch).watch do |changes|
54
- changes.each_key do |filename|
55
- relative_filename = filename.gsub("#{Dir.pwd}/", "")
56
-
57
- Builder.new(files_to_process: [relative_filename]).build if relative_filename.start_with?(*folders_to_watch)
58
- end
59
-
60
- yield if block_given?
61
- end
62
- end
63
-
64
- def run_tailwind(tailwind_input_file, tailwind_output_file)
65
- puts "Running Tailwind CSS build..."
66
-
67
- system("tailwindcss", "-i", tailwind_input_file, "-o", tailwind_output_file)
68
- end
12
+ def self.watch(...)
13
+ Watcher.new(...).watch
69
14
  end
70
15
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_theme_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Massimiliano Lattanzio
@@ -87,6 +87,7 @@ files:
87
87
  - lib/shopify_theme_builder.rb
88
88
  - lib/shopify_theme_builder/builder.rb
89
89
  - lib/shopify_theme_builder/command_line.rb
90
+ - lib/shopify_theme_builder/filewatcher.rb
90
91
  - lib/shopify_theme_builder/liquid_processor.rb
91
92
  - lib/shopify_theme_builder/version.rb
92
93
  - lib/shopify_theme_builder/watcher.rb