ts-morph 0.1.1

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.
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'ts/morph'
6
+
7
+ # Ensure Node dependencies are installed
8
+ unless Ts::Morph.service_available?
9
+ puts "Installing Node.js dependencies..."
10
+ Ts::Morph.install_dependencies
11
+ end
12
+
13
+ # Sample React component code
14
+ code = <<~TSX
15
+ import React from 'react';
16
+
17
+ const LoginForm = () => {
18
+ return (
19
+ <form>
20
+ <input type="email" placeholder="Email" />
21
+ <input type="password" placeholder="Password" />
22
+ <Button>Login</Button>
23
+ <Button>Cancel</Button>
24
+ </form>
25
+ );
26
+ };
27
+
28
+ export default LoginForm;
29
+ TSX
30
+
31
+ puts "Original code:"
32
+ puts code
33
+ puts "\n" + "="*50 + "\n"
34
+
35
+ # Define transformations
36
+ transformations = [
37
+ # Add variant props to buttons
38
+ {
39
+ type: 'addDefaultProps',
40
+ component: 'Button',
41
+ props: { variant: 'primary', size: 'medium' }
42
+ },
43
+ # Wrap form in FormProvider
44
+ {
45
+ type: 'wrapComponents',
46
+ target: 'form',
47
+ wrapper: 'FormProvider'
48
+ },
49
+ # Add necessary imports
50
+ {
51
+ type: 'addImports',
52
+ imports: [
53
+ { from: '@/components/ui', named: ['Button', 'FormProvider'] },
54
+ { from: '@/hooks', named: ['useForm'] }
55
+ ]
56
+ }
57
+ ]
58
+
59
+ # Transform the code
60
+ transformed = Ts::Morph.transform(code, transformations)
61
+
62
+ puts "Transformed code:"
63
+ puts transformed
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example of integrating ts-morph with a Rails application
5
+ # This would typically go in app/services/react_transformer_service.rb
6
+
7
+ require 'bundler/setup'
8
+ require 'ts/morph'
9
+ require 'ts/morph/transformations'
10
+
11
+ class ReactTransformerService
12
+ include Ts::Morph::Transformations
13
+
14
+ class << self
15
+ # Transform React code for a specific site configuration
16
+ def transform_for_site(react_code, site)
17
+ transformations = build_transformations_for_site(site)
18
+ Ts::Morph.transform(react_code, transformations)
19
+ end
20
+
21
+ # Standardize all components in the code
22
+ def standardize_components(react_code)
23
+ transformations = [
24
+ # Ensure all buttons have consistent styling
25
+ add_default_props('Button', {
26
+ variant: 'primary',
27
+ size: 'medium',
28
+ className: 'transition-all duration-200'
29
+ }),
30
+
31
+ # Wrap forms with validation provider
32
+ wrap_components('form', 'FormProvider'),
33
+
34
+ # Add standard imports
35
+ add_imports([
36
+ import_spec(from: '@/components/ui', named: ['Button', 'Card', 'Input']),
37
+ import_spec(from: '@/lib/utils', named: ['cn']),
38
+ import_spec(from: 'react', named: ['useState', 'useEffect'])
39
+ ])
40
+ ]
41
+
42
+ Ts::Morph.transform(react_code, transformations)
43
+ end
44
+
45
+ # Apply a theme to components
46
+ def apply_theme(react_code, theme_name)
47
+ theme = load_theme(theme_name)
48
+
49
+ transformations = [
50
+ inject_styles(theme[:component_styles]),
51
+ add_imports([import_spec(from: '@/themes', default: 'theme')])
52
+ ]
53
+
54
+ Ts::Morph.transform(react_code, transformations)
55
+ end
56
+
57
+ private
58
+
59
+ def build_transformations_for_site(site)
60
+ transformations = []
61
+
62
+ # Add site-specific button styling
63
+ if site.button_style
64
+ transformations << add_default_props('Button',
65
+ site.button_style.symbolize_keys
66
+ )
67
+ end
68
+
69
+ # Apply site theme
70
+ if site.theme_name
71
+ theme = load_theme(site.theme_name)
72
+ transformations << inject_styles(theme[:component_styles])
73
+ end
74
+
75
+ # Add site-specific imports
76
+ if site.uses_analytics?
77
+ transformations << add_imports([
78
+ import_spec(from: '@/analytics', named: ['trackEvent'])
79
+ ])
80
+ end
81
+
82
+ transformations
83
+ end
84
+
85
+ def load_theme(theme_name)
86
+ themes = {
87
+ 'modern' => {
88
+ component_styles: {
89
+ 'Container' => {
90
+ padding: '2rem',
91
+ maxWidth: '1200px',
92
+ margin: '0 auto'
93
+ },
94
+ 'Card' => {
95
+ borderRadius: '12px',
96
+ boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
97
+ padding: '1.5rem'
98
+ },
99
+ 'Button' => {
100
+ borderRadius: '8px',
101
+ fontWeight: '600'
102
+ }
103
+ }
104
+ },
105
+ 'minimal' => {
106
+ component_styles: {
107
+ 'Container' => {
108
+ padding: '1rem',
109
+ maxWidth: '960px',
110
+ margin: '0 auto'
111
+ },
112
+ 'Card' => {
113
+ border: '1px solid #e5e5e5',
114
+ padding: '1rem'
115
+ },
116
+ 'Button' => {
117
+ border: '1px solid currentColor',
118
+ background: 'transparent'
119
+ }
120
+ }
121
+ }
122
+ }
123
+
124
+ themes[theme_name] || themes['modern']
125
+ end
126
+ end
127
+ end
128
+
129
+ # Example usage
130
+ if __FILE__ == $0
131
+ # Sample component
132
+ component_code = <<~TSX
133
+ import React from 'react';
134
+
135
+ const Dashboard = () => {
136
+ return (
137
+ <Container>
138
+ <h1>Welcome to Dashboard</h1>
139
+ <Card>
140
+ <h2>Your Stats</h2>
141
+ <Button onClick={() => console.log('Refresh')}>
142
+ Refresh Data
143
+ </Button>
144
+ </Card>
145
+ </Container>
146
+ );
147
+ };
148
+
149
+ export default Dashboard;
150
+ TSX
151
+
152
+ puts "Original component:"
153
+ puts component_code
154
+ puts "\n" + "="*50 + "\n"
155
+
156
+ # Mock site object
157
+ Site = Struct.new(:button_style, :theme_name, :uses_analytics?) do
158
+ def uses_analytics?
159
+ self[:uses_analytics?] || false
160
+ end
161
+ end
162
+
163
+ site = Site.new(
164
+ { variant: 'primary', size: 'large' },
165
+ 'modern',
166
+ true
167
+ )
168
+
169
+ # Transform for site
170
+ transformed = ReactTransformerService.transform_for_site(component_code, site)
171
+
172
+ puts "Transformed for site:"
173
+ puts transformed
174
+ end