shopify_theme_builder 0.2.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: de0bb008961c3b947c4496bd5605d24144073d22d4c721587b3f529073ed1096
4
- data.tar.gz: 4e494faa701e5bd4dd47c9b609155626bab03438d85cc7a3603bd9e42e5a0ca3
3
+ metadata.gz: 96de2b7ebf1688b16c967eb0a10fc193b0ba49064f0612a2a8ae7b73d8ff5ca4
4
+ data.tar.gz: e8db2e1b3643c1f2b479a4e87c03c00e1c2c8e3354ec7914dca566eabab82746
5
5
  SHA512:
6
- metadata.gz: bd5f70a0f803adcef6eba571c822f8d7d1b45de0c24aa0360c84bc4c19c431357426d53c471c7735e3e3fdd72d1f7774d2f9d141b90409f59402e52d6f6f8cf4
7
- data.tar.gz: 94d70495fd131b5201586e2035c0d4c1ca862718547a112afb755c88b20eb3d34ba3658995c30c252de369dd60010221a213a0cd6d6d600c682a4e34adf60c9c
6
+ metadata.gz: 1bbc6a322bd5a4bb4156e5692c49fa7358b962da211453289a9e9ad7bb419d76b0e28508b4fa41ec6f6eb662436d3b79c16d4e5a6a2ae46d130cb79b9faae1b4
7
+ data.tar.gz: ce8c3198cc5d190ca41d7e1e46f69a3c59fa3649735d74c11bcc42c37eefb950723484453e6fd909785273323c257cab39711eafbb4a5bec9da3e19d47be3ec1
data/README.md CHANGED
@@ -33,12 +33,48 @@ _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
  ```
39
44
 
40
45
  All files inside the `button` folder will be compiled into a single `button.liquid` file in the `blocks` folder, combining the comment, doc, Liquid, JSON, CSS, and JavaScript code.
41
46
 
47
+ ## Tailwind CSS Support
48
+
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.
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.
42
78
 
43
79
  ## Installation
44
80
 
@@ -53,38 +89,46 @@ bundle add shopify_theme_builder --group "development"
53
89
  To watch for changes in the default components folder and build the theme, run:
54
90
 
55
91
  ```bash
56
- bundle exec theme-watcher
92
+ bundle exec theme-builder watch
57
93
  ```
58
94
 
59
- You can customize the components folder by passing options:
95
+ You can customize multiple options when running the watcher:
96
+ - `--folders`: Specify one or more folders to watch (default is `_components`).
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`).
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`).
101
+
102
+ If you need help with all available options, or how to set them, run:
60
103
 
61
104
  ```bash
62
- bundle exec theme-watcher my_components
105
+ bundle exec theme-builder help watch
63
106
  ```
64
107
 
65
- If you prefer, you can import the watcher executable locally using:
108
+ ## After Running the Watcher
66
109
 
67
- ```bash
68
- bundle binstubs shopify_theme_builder
110
+ The watcher will create a CSS file that can be included in your Shopify theme layout in this way:
111
+
112
+ ```liquid
113
+ {{ 'tailwind-output.css' | asset_url | stylesheet_tag }}
69
114
  ```
70
115
 
71
- It will create a `bin/theme-watcher` file that you can run with:
116
+ And a JavaScript file that can be included in your Shopify theme layout in this way:
72
117
 
73
- ```bash
74
- bin/theme-watcher
118
+ ```liquid
119
+ <script type="module" src="{{ 'controllers.js' | asset_url }}"></script>
75
120
  ```
76
121
 
77
-
78
122
  ## Development
79
123
 
80
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.
81
125
 
82
126
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, run `bin/release VERSION`, which will update the version file, create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
83
127
 
84
- ## TODO
128
+ ## Next Steps
85
129
 
86
- - [ ] Run the tailwind build process automatically.
87
- - [ ] Check if stimulus controllers are loaded correctly in Shopify themes.
130
+ - [x] Run the tailwind build process automatically.
131
+ - [x] Add Stimulus JS support.
88
132
  - [ ] Create a command to build an example component with all the files.
89
133
  - [ ] Decompile existing Shopify files into components structure (?).
90
134
 
data/exe/theme-builder ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "shopify_theme_builder"
6
+
7
+ ShopifyThemeBuilder::CommandLine.start(ARGV)
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ module ShopifyThemeBuilder
6
+ # CommandLine class to handle CLI commands using Thor.
7
+ class CommandLine < Thor
8
+ desc "watch", "Watch for changes in the components folder and build the theme accordingly"
9
+ method_option :folders, type: :array, default: ["_components"], desc: "Folders to watch for changes"
10
+ method_option :tailwind_input_file, type: :string, default: "./assets/tailwind.css", desc: "Tailwind CSS input file"
11
+ method_option :tailwind_output_file, type: :string, default: "./assets/tailwind-output.css",
12
+ desc: "Tailwind CSS output file"
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"
16
+ def watch
17
+ ShopifyThemeBuilder.watch(
18
+ folders_to_watch: options[:folders],
19
+ tailwind_input_file: options[:tailwind_input_file],
20
+ tailwind_output_file: options[:tailwind_output_file],
21
+ skip_tailwind: options[:skip_tailwind],
22
+ stimulus_output_file: options[:stimulus_output_file]
23
+ )
24
+ end
25
+ end
26
+ 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.2.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,52 +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"
7
+ require_relative "shopify_theme_builder/command_line"
8
+ require_relative "shopify_theme_builder/watcher"
9
9
 
10
10
  # The main module for ShopifyThemeBuilder.
11
11
  module ShopifyThemeBuilder
12
- class << self
13
- def watch(folders_to_watch: ["_components"])
14
- create_folders(folders_to_watch)
15
-
16
- initial_build(folders_to_watch)
17
-
18
- watch_folders(folders_to_watch)
19
- end
20
-
21
- private
22
-
23
- def create_folders(folders_to_watch)
24
- puts "Creating necessary folders..."
25
-
26
- FileUtils.mkdir_p(folders_to_watch)
27
- FileUtils.mkdir_p("sections")
28
- FileUtils.mkdir_p("blocks")
29
- FileUtils.mkdir_p("snippets")
30
- end
31
-
32
- def initial_build(folders_to_watch)
33
- puts "Doing an initial build..."
34
-
35
- folders_to_watch.each do |folder|
36
- Builder.new(files_to_process: Dir.glob("#{folder}/**/*.*")).build
37
- end
38
- end
39
-
40
- def watch_folders(folders_to_watch)
41
- puts "Watching for changes in '#{folders_to_watch.join(", ")}' folders..."
42
-
43
- Watcher.new(folders_to_watch).watch do |changes|
44
- changes.each_key do |filename|
45
- relative_filename = filename.gsub("#{Dir.pwd}/", "")
46
-
47
- Builder.new(files_to_process: [relative_filename]).build if relative_filename.start_with?(*folders_to_watch)
48
- end
49
- end
50
- end
12
+ def self.watch(...)
13
+ Watcher.new(...).watch
51
14
  end
52
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.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Massimiliano Lattanzio
@@ -38,10 +38,44 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: tailwindcss-ruby
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '5.0'
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '3.0'
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '5.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: thor
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.4'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.4'
41
75
  email:
42
76
  - massimiliano.lattanzio@gmail.com
43
77
  executables:
44
- - theme-watcher
78
+ - theme-builder
45
79
  extensions: []
46
80
  extra_rdoc_files: []
47
81
  files:
@@ -49,9 +83,11 @@ files:
49
83
  - LICENSE.txt
50
84
  - README.md
51
85
  - Rakefile
52
- - exe/theme-watcher
86
+ - exe/theme-builder
53
87
  - lib/shopify_theme_builder.rb
54
88
  - lib/shopify_theme_builder/builder.rb
89
+ - lib/shopify_theme_builder/command_line.rb
90
+ - lib/shopify_theme_builder/filewatcher.rb
55
91
  - lib/shopify_theme_builder/liquid_processor.rb
56
92
  - lib/shopify_theme_builder/version.rb
57
93
  - lib/shopify_theme_builder/watcher.rb
data/exe/theme-watcher DELETED
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "bundler/setup"
5
- require "shopify_theme_builder"
6
-
7
- $stdout.sync = true
8
-
9
- if ARGV.empty?
10
- ShopifyThemeBuilder.watch
11
- else
12
- ShopifyThemeBuilder.watch(folders_to_watch: ARGV)
13
- end