svelte-on-rails 0.0.29 → 0.0.30
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 +4 -4
- data/lib/svelte-on-rails.rb +4 -1
- data/lib/svelte_on_rails/{compile.js → compiler/compile.js} +21 -78
- data/lib/svelte_on_rails/compiler/compiler.rb +115 -0
- data/lib/svelte_on_rails/compiler/customPlugins.js +60 -0
- data/lib/svelte_on_rails/configuration.rb +6 -1
- data/lib/svelte_on_rails/lib/initializable.rb +17 -0
- data/lib/svelte_on_rails/lib/utils.rb +35 -0
- data/lib/svelte_on_rails/renderer/render.js +19 -0
- data/lib/svelte_on_rails/renderer/renderer.rb +52 -0
- data/lib/svelte_on_rails/renderer/utils.js +39 -0
- data/lib/svelte_on_rails/view_helpers.rb +5 -4
- metadata +10 -5
- data/lib/svelte_on_rails/render.js +0 -65
- data/lib/svelte_on_rails/render_server_side.rb +0 -156
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 343a3e6cdeed188bf622f4152032d851ab1db1b36cb36be7b4948df673d2cb13
|
4
|
+
data.tar.gz: cd28b8497abeff07f802e0ab71ac543ccb61e1504587ff79bcbbea5c1aeb2fec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84a171bc560f4fe9e4ffe2ec5017f92a2e046f0e146f979f5282344ca20c195215730e6b43f2b798c810e6bc1d7840f1f095fd3a6af6b30f0b84e0589d4792cb
|
7
|
+
data.tar.gz: 8f091933d50d584686825c5c4a5dcd75f740194af2d81765ccc6b060aafd25c017a6e0f0a4b3b84c21c6e1d47a470b95b6c1761e0b20778df56aa0c0df07f2c5
|
data/lib/svelte-on-rails.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require "svelte_on_rails/configuration"
|
2
2
|
require "svelte_on_rails/view_helpers"
|
3
|
-
require "svelte_on_rails/
|
3
|
+
require "svelte_on_rails/renderer/renderer"
|
4
|
+
require "svelte_on_rails/compiler/compiler"
|
5
|
+
require "svelte_on_rails/lib/utils"
|
6
|
+
require "svelte_on_rails/lib/initializable"
|
4
7
|
require "svelte_on_rails/railtie" if defined?(Rails)
|
5
8
|
|
6
9
|
# installer
|
@@ -2,24 +2,25 @@
|
|
2
2
|
|
3
3
|
import path from 'path';
|
4
4
|
import fs from 'fs/promises';
|
5
|
+
import {rawResolver, stringPlugin, ssrExternals} from "./customPlugins.js";
|
5
6
|
|
6
|
-
//
|
7
|
+
// Arguments: inputFile, outputDir, gemPath
|
7
8
|
const args = process.argv.slice(2);
|
8
9
|
const inputFile = args[0];
|
9
10
|
const outputDir = args[1];
|
10
11
|
const gemPath = args[2];
|
11
12
|
|
12
13
|
if (!inputFile || !outputDir || !gemPath) {
|
13
|
-
console.error('
|
14
|
-
console.error('
|
14
|
+
console.error('Error: inputFile, outputDir, and gemPath must be specified.');
|
15
|
+
console.error('Usage: node script.js <inputFile> <outputDir> <gemPath>');
|
15
16
|
process.exit(1);
|
16
17
|
}
|
17
18
|
|
18
|
-
//
|
19
|
+
// Ensure that gemPath exists
|
19
20
|
try {
|
20
21
|
await fs.access(gemPath);
|
21
22
|
} catch (error) {
|
22
|
-
console.error(`
|
23
|
+
console.error(`Error: The gemPath "${gemPath}" does not exist.`);
|
23
24
|
process.exit(1);
|
24
25
|
}
|
25
26
|
|
@@ -27,10 +28,10 @@ const fileName = path.basename(inputFile, '.svelte');
|
|
27
28
|
const outputFile = path.join(outputDir, `${fileName}.js`);
|
28
29
|
const outputCss = path.join(outputDir, `${fileName}.css`);
|
29
30
|
|
30
|
-
//
|
31
|
+
// Path to node_modules in the gem
|
31
32
|
const gemNodeModules = path.join(gemPath, 'node_modules');
|
32
33
|
|
33
|
-
//
|
34
|
+
// Dynamic imports of build tools from the gem
|
34
35
|
const { rollup } = await import(path.join(gemNodeModules, 'rollup', 'dist', 'rollup.js'));
|
35
36
|
const svelte = await import(path.join(gemNodeModules, 'rollup-plugin-svelte', 'index.js')).then(m => m.default);
|
36
37
|
const resolve = await import(path.join(gemNodeModules, '@rollup', 'plugin-node-resolve', 'dist', 'es', 'index.js')).then(m => m.default);
|
@@ -39,64 +40,6 @@ const url = await import(path.join(gemNodeModules, '@rollup', 'plugin-url', 'dis
|
|
39
40
|
const css = await import(path.join(gemNodeModules, 'rollup-plugin-css-only', 'dist', 'index.mjs')).then(m => m.default);
|
40
41
|
const { sveltePreprocess } = await import(path.join(gemNodeModules, 'svelte-preprocess', 'dist', 'index.js'));
|
41
42
|
|
42
|
-
// Plugin für Raw-Importe
|
43
|
-
function rawResolver() {
|
44
|
-
return {
|
45
|
-
name: 'raw-resolver',
|
46
|
-
resolveId(source, importer) {
|
47
|
-
console.log(`Raw-Resolver: source=${source}, importer=${importer}`);
|
48
|
-
if (source.endsWith('?raw')) {
|
49
|
-
const actualSource = source.replace('?raw', '');
|
50
|
-
const resolved = path.resolve(path.dirname(importer), actualSource);
|
51
|
-
console.log(`Raw-Resolver: Auflösen von ${source} zu ${resolved}?raw`);
|
52
|
-
return `${resolved}?raw`;
|
53
|
-
}
|
54
|
-
return null;
|
55
|
-
},
|
56
|
-
};
|
57
|
-
}
|
58
|
-
|
59
|
-
function stringPlugin() {
|
60
|
-
return {
|
61
|
-
name: 'string',
|
62
|
-
async load(id) {
|
63
|
-
if (id.endsWith('?raw')) {
|
64
|
-
console.log(`String-Plugin: Lade ${id}`);
|
65
|
-
const actualId = id.replace('?raw', '');
|
66
|
-
try {
|
67
|
-
const content = await fs.readFile(actualId, 'utf-8');
|
68
|
-
console.log(`String-Plugin: Inhalt von ${actualId} geladen (Auszug): ${content.substring(0, 50)}...`);
|
69
|
-
return `export default ${JSON.stringify(content)};`;
|
70
|
-
} catch (error) {
|
71
|
-
console.error(`String-Plugin: Fehler beim Laden von ${actualId}:`, error);
|
72
|
-
throw error;
|
73
|
-
}
|
74
|
-
}
|
75
|
-
return null;
|
76
|
-
},
|
77
|
-
};
|
78
|
-
}
|
79
|
-
|
80
|
-
// Plugin, um browser-spezifische Module im SSR zu ignorieren
|
81
|
-
function ssrExternals() {
|
82
|
-
return {
|
83
|
-
name: 'ssr-externals',
|
84
|
-
resolveId(source) {
|
85
|
-
// Ignoriere Module wie axios während SSR
|
86
|
-
if (source === 'axios' || source.includes('form-data')) {
|
87
|
-
return { id: 'void 0', external: true };
|
88
|
-
}
|
89
|
-
return null;
|
90
|
-
},
|
91
|
-
load(id) {
|
92
|
-
if (id === 'void 0') {
|
93
|
-
return 'export default null;';
|
94
|
-
}
|
95
|
-
return null;
|
96
|
-
}
|
97
|
-
};
|
98
|
-
}
|
99
|
-
|
100
43
|
const rollupConfig = {
|
101
44
|
input: inputFile,
|
102
45
|
output: {
|
@@ -104,17 +47,17 @@ const rollupConfig = {
|
|
104
47
|
format: 'esm',
|
105
48
|
},
|
106
49
|
external: [
|
107
|
-
// Node.js-
|
50
|
+
// Node.js built-ins that should not be bundled
|
108
51
|
'fs', 'path', 'url', 'module', 'http', 'https', 'zlib', 'stream', 'buffer',
|
109
|
-
// Browser-
|
52
|
+
// Browser-specific modules ignored during SSR
|
110
53
|
'axios', 'form-data'
|
111
54
|
],
|
112
55
|
onwarn(warning, warn) {
|
113
|
-
//
|
56
|
+
// Ignore certain warnings, e.g., Circular Dependencies
|
114
57
|
if (warning.code === 'CIRCULAR_DEPENDENCY') {
|
115
58
|
return;
|
116
59
|
}
|
117
|
-
//
|
60
|
+
// Ignore warnings for empty chunks or unused external modules
|
118
61
|
if (warning.code === 'EMPTY_BUNDLE' || warning.code === 'UNUSED_EXTERNAL_IMPORT') {
|
119
62
|
return;
|
120
63
|
}
|
@@ -129,7 +72,7 @@ const rollupConfig = {
|
|
129
72
|
generate: 'ssr',
|
130
73
|
hydratable: false
|
131
74
|
},
|
132
|
-
//
|
75
|
+
// Ignore browser-specific modules during SSR
|
133
76
|
onwarn(warning, handler) {
|
134
77
|
if (warning.code === 'MISSING_EXPORT' && warning.exporter.includes('axios')) {
|
135
78
|
return;
|
@@ -152,32 +95,32 @@ const rollupConfig = {
|
|
152
95
|
exportConditions: ['svelte', 'server'],
|
153
96
|
modulePaths: [gemNodeModules],
|
154
97
|
extensions: ['.mjs', '.js', '.cjs', '.ts'],
|
155
|
-
//
|
98
|
+
// Prefer Node-specific modules
|
156
99
|
mainFields: ['main', 'module']
|
157
100
|
}),
|
158
101
|
commonjs({
|
159
|
-
//
|
102
|
+
// Explicitly handle CommonJS modules
|
160
103
|
include: [/node_modules/],
|
161
|
-
//
|
104
|
+
// Transform mixed ES/CommonJS modules
|
162
105
|
transformMixedEsModules: true
|
163
106
|
}),
|
164
|
-
ssrExternals() //
|
107
|
+
ssrExternals() // New plugin to ignore axios and form-data
|
165
108
|
],
|
166
109
|
};
|
167
110
|
|
168
|
-
// Rollup
|
111
|
+
// Rollup build
|
169
112
|
async function compile() {
|
170
113
|
try {
|
171
114
|
const startTime = performance.now();
|
172
115
|
const bundle = await rollup(rollupConfig);
|
173
116
|
await bundle.write(rollupConfig.output);
|
174
117
|
await bundle.close();
|
175
|
-
console.log(`Build
|
118
|
+
console.log(`Build successful: ${outputFile} and ${outputCss}`);
|
176
119
|
const endTime = performance.now();
|
177
120
|
const duration = (endTime - startTime).toFixed(2);
|
178
|
-
console.log(`
|
121
|
+
console.log(`Execution time: ${duration} ms`);
|
179
122
|
} catch (error) {
|
180
|
-
console.error('Build
|
123
|
+
console.error('Build failed:', error);
|
181
124
|
process.exit(1);
|
182
125
|
}
|
183
126
|
}
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module SvelteOnRails
|
2
|
+
|
3
|
+
class Compiler
|
4
|
+
|
5
|
+
require 'open3'
|
6
|
+
def initialize(filename, base_path: SvelteOnRails::Configuration.instance.components_folder_full)
|
7
|
+
|
8
|
+
utils = SvelteOnRails::Lib::Utils
|
9
|
+
@files = utils.component_files(filename, base_path: base_path)
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
# compiler
|
14
|
+
def compile_if_changes
|
15
|
+
|
16
|
+
# letzte Änderung innerhalb des ordners ermitteln
|
17
|
+
|
18
|
+
watch_changes = SvelteOnRails::Configuration.instance.watch_changes?
|
19
|
+
ts_file = SvelteOnRails::Configuration.instance.dist_folder.join('reset_timestamp')
|
20
|
+
|
21
|
+
have_changes = if watch_changes && File.exist?(ts_file)
|
22
|
+
|
23
|
+
# compare last modification timestamp
|
24
|
+
last_modification = 100.years.ago.to_time
|
25
|
+
Dir.glob("#{SvelteOnRails::Configuration.instance.components_folder}**/*").each do |path|
|
26
|
+
if File.file?(path)
|
27
|
+
mtime = File.mtime(path)
|
28
|
+
if mtime > last_modification
|
29
|
+
last_modification = mtime
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
File.mtime(ts_file) < last_modification
|
34
|
+
|
35
|
+
elsif watch_changes
|
36
|
+
true
|
37
|
+
elsif !File.exist?(ts_file)
|
38
|
+
true
|
39
|
+
else
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
if have_changes || !File.exist?(compiled_js_file) || !File.exist?(compiled_css_file)
|
44
|
+
if have_changes || (!File.exist?(ts_file) && watch_changes)
|
45
|
+
self.class.reset_dist
|
46
|
+
end
|
47
|
+
compile
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def compiled_js_file
|
52
|
+
@files[:compiled_file] + '.js'
|
53
|
+
end
|
54
|
+
|
55
|
+
def compiled_css_file
|
56
|
+
@files[:compiled_file] + '.css'
|
57
|
+
end
|
58
|
+
|
59
|
+
def compiled_file
|
60
|
+
@files[:compiled_file]
|
61
|
+
end
|
62
|
+
|
63
|
+
def compile
|
64
|
+
|
65
|
+
start_time = Time.now
|
66
|
+
|
67
|
+
cnf = SvelteOnRails::Configuration.instance
|
68
|
+
subs = @files[:svelte_filename].split('/')[0..-2].join('/')
|
69
|
+
dist = cnf.dist_folder + cnf.components_folder + subs
|
70
|
+
utils = SvelteOnRails::Lib::Utils
|
71
|
+
|
72
|
+
cmd = [
|
73
|
+
'node',
|
74
|
+
utils.gem_app_dir + 'compiler/compile.js',
|
75
|
+
@files[:svelte_file],
|
76
|
+
dist,
|
77
|
+
utils.gem_app_dir
|
78
|
+
].join(' ')
|
79
|
+
|
80
|
+
stdout, stderr, status = Open3.capture3(cmd, chdir: SvelteOnRails::Configuration.instance.rails_root)
|
81
|
+
|
82
|
+
unless status.to_s.match(/^pid [0-9]+ exit 0$/)
|
83
|
+
raise "Compiling «#{@files[:svelte_filename]}» Server-side, script compile.js, executed within Rails.root:\n\n#{cmd}\n\n++++++\n\n#{stderr}\n\n++++++\n\n"
|
84
|
+
end
|
85
|
+
|
86
|
+
time = Time.now - start_time
|
87
|
+
Rails.logger.info " Compiled #{@files[:svelte_filename]}.js: #{time.round(3)}ms" rescue nil
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.reset_dist
|
91
|
+
unless Dir.exist?(SvelteOnRails::Configuration.instance.dist_folder)
|
92
|
+
FileUtils.mkdir_p(SvelteOnRails::Configuration.instance.dist_folder)
|
93
|
+
end
|
94
|
+
FileUtils.rm_rf Dir.glob("#{SvelteOnRails::Configuration.instance.dist_folder}/*")
|
95
|
+
FileUtils.touch SvelteOnRails::Configuration.instance.dist_folder.join('reset_timestamp')
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.reset_and_compile_all
|
99
|
+
SvelteOnRails::RenderServerSide.reset_dist
|
100
|
+
cnf = SvelteOnRails::Configuration.instance
|
101
|
+
frontend_folder = cnf.frontend_folder_full
|
102
|
+
sveltes = Dir.glob(cnf.frontend_folder_full.join('**/*.svelte'))
|
103
|
+
sveltes.each_with_index do |file, ind|
|
104
|
+
comp_name = file.to_s[(cnf.frontend_folder_full.to_s.length + 1)..-1]
|
105
|
+
|
106
|
+
n = SvelteOnRails::RenderServerSide.new(comp_name, base_path: frontend_folder)
|
107
|
+
n.compile
|
108
|
+
|
109
|
+
puts "compiled #{ind + 1}/#{sveltes.length}: #{comp_name}"
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import path from 'path';
|
2
|
+
import fs from 'fs/promises';
|
3
|
+
|
4
|
+
// Plugin for raw imports
|
5
|
+
export function rawResolver() {
|
6
|
+
return {
|
7
|
+
name: 'raw-resolver',
|
8
|
+
resolveId(source, importer) {
|
9
|
+
console.log(`Raw-Resolver: source=${source}, importer=${importer}`);
|
10
|
+
if (source.endsWith('?raw')) {
|
11
|
+
const actualSource = source.replace('?raw', '');
|
12
|
+
const resolved = path.resolve(path.dirname(importer), actualSource);
|
13
|
+
console.log(`Raw-Resolver: Resolving ${source} to ${resolved}?raw`);
|
14
|
+
return `${resolved}?raw`;
|
15
|
+
}
|
16
|
+
return null;
|
17
|
+
},
|
18
|
+
};
|
19
|
+
}
|
20
|
+
|
21
|
+
export function stringPlugin() {
|
22
|
+
return {
|
23
|
+
name: 'string',
|
24
|
+
async load(id) {
|
25
|
+
if (id.endsWith('?raw')) {
|
26
|
+
console.log(`String-Plugin: Loading ${id}`);
|
27
|
+
const actualId = id.replace('?raw', '');
|
28
|
+
try {
|
29
|
+
const content = await fs.readFile(actualId, 'utf-8');
|
30
|
+
console.log(`String-Plugin: Content of ${actualId} loaded (excerpt): ${content.substring(0, 50)}...`);
|
31
|
+
return `export default ${JSON.stringify(content)};`;
|
32
|
+
} catch (error) {
|
33
|
+
console.error(`String-Plugin: Error loading ${actualId}:`, error);
|
34
|
+
throw error;
|
35
|
+
}
|
36
|
+
}
|
37
|
+
return null;
|
38
|
+
},
|
39
|
+
};
|
40
|
+
}
|
41
|
+
|
42
|
+
// Plugin to ignore browser-specific modules during SSR
|
43
|
+
export function ssrExternals() {
|
44
|
+
return {
|
45
|
+
name: 'ssr-externals',
|
46
|
+
resolveId(source) {
|
47
|
+
// Ignore modules like axios during SSR
|
48
|
+
if (source === 'axios' || source.includes('form-data')) {
|
49
|
+
return { id: 'void 0', external: true };
|
50
|
+
}
|
51
|
+
return null;
|
52
|
+
},
|
53
|
+
load(id) {
|
54
|
+
if (id === 'void 0') {
|
55
|
+
return 'export default null;';
|
56
|
+
}
|
57
|
+
return null;
|
58
|
+
}
|
59
|
+
};
|
60
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module SvelteOnRails
|
2
|
+
|
3
|
+
module Lib
|
4
|
+
module Initializable
|
5
|
+
def initialize(filename, base_path: SvelteOnRails::Configuration.instance.components_folder_full)
|
6
|
+
|
7
|
+
fn = (filename.match(/\.svelte$/) ? filename[0..-8] : filename)
|
8
|
+
@svelte_file = base_path + filename
|
9
|
+
@svelte_filename = filename
|
10
|
+
cnf = SvelteOnRails::Configuration.instance
|
11
|
+
cf = cnf.dist_folder + cnf.components_folder + fn
|
12
|
+
@compiled_file = cf.to_s
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module SvelteOnRails
|
2
|
+
module Lib
|
3
|
+
class Utils
|
4
|
+
|
5
|
+
def self.gem_app_dir
|
6
|
+
File.expand_path('../../svelte_on_rails', __dir__) + '/'
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.file_exist_case_sensitive?(containing_dir, filename)
|
10
|
+
# Combine the directory path and filename
|
11
|
+
full_path = File.join(containing_dir, filename)
|
12
|
+
|
13
|
+
# Check if the file exists and the path matches case-sensitively
|
14
|
+
File.exist?(full_path) && Dir[File.join(containing_dir, "**/*")].any? do |f|
|
15
|
+
f == full_path
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.component_files(filename, base_path: SvelteOnRails::Configuration.instance.components_folder_full)
|
20
|
+
fn = (filename.match(/\.svelte$/) ? filename[0..-8] : filename)
|
21
|
+
svelte_file = (base_path + fn).to_s + '.svelte'
|
22
|
+
svelte_filename = fn + '.svelte'
|
23
|
+
cnf = SvelteOnRails::Configuration.instance
|
24
|
+
cf = cnf.dist_folder + cnf.components_folder + fn
|
25
|
+
|
26
|
+
{
|
27
|
+
svelte_file: svelte_file,
|
28
|
+
svelte_filename: svelte_filename,
|
29
|
+
compiled_file: cf.to_s
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import {loadComponentModule, readPropsFromStdin} from './utils.js';
|
2
|
+
|
3
|
+
(async () => {
|
4
|
+
|
5
|
+
const MyComponent = await loadComponentModule(process.argv[2]);
|
6
|
+
const props = await readPropsFromStdin();
|
7
|
+
const payload = {out: ''};
|
8
|
+
|
9
|
+
try {
|
10
|
+
MyComponent(payload, props); // Writes directly to payload.out
|
11
|
+
} catch (error) {
|
12
|
+
console.error('Error rendering component:', error);
|
13
|
+
process.exit(1);
|
14
|
+
}
|
15
|
+
|
16
|
+
const res = {status: 'SUCCESS', html: payload.out};
|
17
|
+
console.log(JSON.stringify(res));
|
18
|
+
})();
|
19
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module SvelteOnRails
|
2
|
+
class Renderer
|
3
|
+
|
4
|
+
require 'open3'
|
5
|
+
|
6
|
+
def initialize(compiled_file: nil, component_name: nil, base_path: SvelteOnRails::Configuration.instance.components_folder_full)
|
7
|
+
|
8
|
+
@compiled_file = if compiled_file
|
9
|
+
compiled_file
|
10
|
+
elsif component_name
|
11
|
+
utils = SvelteOnRails::Lib::Utils
|
12
|
+
cf = utils.component_files(component_name, base_path: base_path)
|
13
|
+
cf[:compiled_file]
|
14
|
+
else
|
15
|
+
raise "Either compiled_file or component_name must be given"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# render
|
20
|
+
|
21
|
+
def render(props = {})
|
22
|
+
require 'base64'
|
23
|
+
require 'json'
|
24
|
+
utils = SvelteOnRails::Lib::Utils
|
25
|
+
|
26
|
+
cmd = [
|
27
|
+
'node',
|
28
|
+
'/Users/christian/projects-gmbh/gems/svelte-on-rails/svelte-on-rails-gem/lib/svelte_on_rails/renderer/render.js',
|
29
|
+
@compiled_file + '.js',
|
30
|
+
SvelteOnRails::Configuration.instance.rails_root
|
31
|
+
].join(' ')
|
32
|
+
|
33
|
+
stdout, stderr, status = Open3.capture3(cmd, stdin_data: props.to_json, chdir: utils.gem_app_dir)
|
34
|
+
|
35
|
+
unless status.to_s.match(/^pid [0-9]+ exit 0$/)
|
36
|
+
raise "Render Svelte Server-side =>\n#{cmd}\n\nError output from render.js (stderr) =>\n+++\n" + stderr + "+++\n\n"
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
res = JSON.parse(stdout)
|
41
|
+
css_file = @compiled_file + '.css'
|
42
|
+
if File.exist?(css_file)
|
43
|
+
res['css'] = File.read(css_file)
|
44
|
+
end
|
45
|
+
return res
|
46
|
+
rescue JSON::ParserError => e
|
47
|
+
raise "Render Svelte Server-side: Expected JSON, got: «#{stdout}»"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import {fileURLToPath} from 'node:url';
|
2
|
+
import {dirname, resolve} from 'node:path';
|
3
|
+
|
4
|
+
export async function loadComponentModule(compiledFile) {
|
5
|
+
// Get the directory of the current script
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
7
|
+
const __dirname = dirname(__filename);
|
8
|
+
|
9
|
+
try {
|
10
|
+
// Convert relative path to absolute path
|
11
|
+
const absolutePath = resolve(__dirname, compiledFile);
|
12
|
+
|
13
|
+
// Convert absolute path to a file URL
|
14
|
+
const modulePath = `file://${absolutePath}`;
|
15
|
+
|
16
|
+
// Import the module
|
17
|
+
const module = await import(modulePath);
|
18
|
+
return module.default;
|
19
|
+
} catch (error) {
|
20
|
+
console.error(`Error loading component from ${compiledFile}:`, error);
|
21
|
+
process.exit(1);
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
export function readPropsFromStdin() {
|
26
|
+
return new Promise((resolve, reject) => {
|
27
|
+
let input = '';
|
28
|
+
process.stdin.setEncoding('utf8');
|
29
|
+
process.stdin.on('data', (chunk) => (input += chunk));
|
30
|
+
process.stdin.on('end', () => {
|
31
|
+
try {
|
32
|
+
resolve(JSON.parse(input));
|
33
|
+
} catch (error) {
|
34
|
+
reject(new Error(`Error parsing JSON from STDIN: ${error.message}\nInput: «${input}»`));
|
35
|
+
}
|
36
|
+
});
|
37
|
+
process.stdin.on('error', (error) => reject(new Error(`Error reading STDIN: ${error.message}`)));
|
38
|
+
});
|
39
|
+
}
|
@@ -9,7 +9,7 @@ module SvelteOnRails
|
|
9
9
|
file_path = cff + "#{filename}.svelte"
|
10
10
|
if !File.exist?(file_path)
|
11
11
|
raise file_not_found_messsage(filename)
|
12
|
-
elsif conf.watch_changes? && !SvelteOnRails::
|
12
|
+
elsif conf.watch_changes? && !SvelteOnRails::Lib::Utils.file_exist_case_sensitive?(cff, filename + '.svelte')
|
13
13
|
# on development environments we check case sensitivity too
|
14
14
|
msg = "File found but Upper and lower case letters are incorrect\n" +
|
15
15
|
"(This check is only on development environments when watch_changes is true):\n."
|
@@ -56,9 +56,10 @@ module SvelteOnRails
|
|
56
56
|
# render server side
|
57
57
|
|
58
58
|
start_time = Time.now
|
59
|
-
|
60
|
-
|
61
|
-
|
59
|
+
comp = SvelteOnRails::Compiler.new(filename)
|
60
|
+
comp.compile_if_changes
|
61
|
+
rend = SvelteOnRails::Renderer.new(compiled_file: comp.compiled_file)
|
62
|
+
res = rend.render(props)
|
62
63
|
time = Time.now - start_time
|
63
64
|
Rails.logger.info " Rendered #{filename}.svelte server-side: #{time.round(3)}ms"
|
64
65
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: svelte-on-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.30
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Sedlmair
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-05-
|
11
|
+
date: 2025-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -32,7 +32,9 @@ extra_rdoc_files: []
|
|
32
32
|
files:
|
33
33
|
- README.md
|
34
34
|
- lib/svelte-on-rails.rb
|
35
|
-
- lib/svelte_on_rails/compile.js
|
35
|
+
- lib/svelte_on_rails/compiler/compile.js
|
36
|
+
- lib/svelte_on_rails/compiler/compiler.rb
|
37
|
+
- lib/svelte_on_rails/compiler/customPlugins.js
|
36
38
|
- lib/svelte_on_rails/configuration.rb
|
37
39
|
- lib/svelte_on_rails/installer/gem_utils.rb
|
38
40
|
- lib/svelte_on_rails/installer/haml.rb
|
@@ -53,6 +55,8 @@ files:
|
|
53
55
|
- lib/svelte_on_rails/installer/svelte.rb
|
54
56
|
- lib/svelte_on_rails/installer/utils.rb
|
55
57
|
- lib/svelte_on_rails/installer/vite.rb
|
58
|
+
- lib/svelte_on_rails/lib/initializable.rb
|
59
|
+
- lib/svelte_on_rails/lib/utils.rb
|
56
60
|
- lib/svelte_on_rails/node_modules/@ampproject/remapping/LICENSE
|
57
61
|
- lib/svelte_on_rails/node_modules/@ampproject/remapping/README.md
|
58
62
|
- lib/svelte_on_rails/node_modules/@ampproject/remapping/dist/remapping.mjs
|
@@ -1404,8 +1408,9 @@ files:
|
|
1404
1408
|
- lib/svelte_on_rails/package-lock.json
|
1405
1409
|
- lib/svelte_on_rails/package.json
|
1406
1410
|
- lib/svelte_on_rails/railtie.rb
|
1407
|
-
- lib/svelte_on_rails/render.js
|
1408
|
-
- lib/svelte_on_rails/
|
1411
|
+
- lib/svelte_on_rails/renderer/render.js
|
1412
|
+
- lib/svelte_on_rails/renderer/renderer.rb
|
1413
|
+
- lib/svelte_on_rails/renderer/utils.js
|
1409
1414
|
- lib/svelte_on_rails/view_helpers.rb
|
1410
1415
|
- lib/tasks/svelte_on_rails_tasks.rake
|
1411
1416
|
homepage: https://gitlab.com/sedl/svelte-on-rails
|
@@ -1,65 +0,0 @@
|
|
1
|
-
import { existsSync } from 'node:fs';
|
2
|
-
import { join, dirname, resolve } from 'node:path';
|
3
|
-
import { fileURLToPath } from 'node:url';
|
4
|
-
|
5
|
-
// Get the directory of the current script
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
7
|
-
const __dirname = dirname(__filename);
|
8
|
-
|
9
|
-
// Command line arguments
|
10
|
-
const compiledFile = process.argv[2]; // Path to the compiled JavaScript file
|
11
|
-
let args;
|
12
|
-
|
13
|
-
try {
|
14
|
-
const base64Input = process.argv[3];
|
15
|
-
if (!base64Input) {
|
16
|
-
throw new Error('No Base64-encoded argument received in process.argv[3]');
|
17
|
-
}
|
18
|
-
|
19
|
-
let decodedString;
|
20
|
-
try {
|
21
|
-
decodedString = atob(base64Input);
|
22
|
-
} catch (decodeError) {
|
23
|
-
throw new Error(`Error decoding Base64 string: ${decodeError.message}\nInput (process.argv[3]): «${base64Input}»`);
|
24
|
-
}
|
25
|
-
|
26
|
-
try {
|
27
|
-
args = JSON.parse(decodedString);
|
28
|
-
} catch (parseError) {
|
29
|
-
throw new Error(`Error parsing JSON: ${parseError.message}\nInput (process.argv[3]): «${base64Input}»\nDecoded string: «${decodedString}»`);
|
30
|
-
}
|
31
|
-
} catch (error) {
|
32
|
-
console.error('Error processing command line arguments:', error.message);
|
33
|
-
process.exit(1);
|
34
|
-
}
|
35
|
-
|
36
|
-
let MyComponent;
|
37
|
-
(async () => {
|
38
|
-
try {
|
39
|
-
// Convert relative path to absolute path
|
40
|
-
const absolutePath = resolve(__dirname, compiledFile);
|
41
|
-
|
42
|
-
// Convert absolute path to a file URL
|
43
|
-
const modulePath = `file://${absolutePath}`;
|
44
|
-
|
45
|
-
// Import the module
|
46
|
-
const module = await import(modulePath);
|
47
|
-
MyComponent = module.default;
|
48
|
-
} catch (error) {
|
49
|
-
console.error(`Error loading component from ${compiledFile}:`, error);
|
50
|
-
process.exit(1);
|
51
|
-
}
|
52
|
-
|
53
|
-
const props = args;
|
54
|
-
const payload = { out: '' };
|
55
|
-
|
56
|
-
try {
|
57
|
-
MyComponent(payload, props); // Writes directly to payload.out
|
58
|
-
} catch (error) {
|
59
|
-
console.error('Error rendering component:', error);
|
60
|
-
process.exit(1);
|
61
|
-
}
|
62
|
-
|
63
|
-
const res = { status: 'SUCCESS', html: payload.out };
|
64
|
-
console.log(JSON.stringify(res));
|
65
|
-
})();
|
@@ -1,156 +0,0 @@
|
|
1
|
-
module SvelteOnRails
|
2
|
-
class RenderServerSide
|
3
|
-
|
4
|
-
require 'open3'
|
5
|
-
|
6
|
-
def initialize(filename, base_path: SvelteOnRails::Configuration.instance.components_folder_full)
|
7
|
-
|
8
|
-
fn = (filename.match(/\.svelte$/) ? filename[0..-8] : filename)
|
9
|
-
@svelte_file = base_path + filename
|
10
|
-
@svelte_filename = filename
|
11
|
-
cnf = SvelteOnRails::Configuration.instance
|
12
|
-
cf = cnf.dist_folder + cnf.components_folder + fn
|
13
|
-
@compiled_file = cf.to_s
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
def compile_if_changes
|
18
|
-
|
19
|
-
# letzte Änderung innerhalb des ordners ermitteln
|
20
|
-
|
21
|
-
watch_changes = SvelteOnRails::Configuration.instance.watch_changes?
|
22
|
-
ts_file = SvelteOnRails::Configuration.instance.dist_folder.join('reset_timestamp')
|
23
|
-
|
24
|
-
have_changes = if watch_changes && File.exist?(ts_file)
|
25
|
-
|
26
|
-
# compare last modification timestamp
|
27
|
-
last_modification = 100.years.ago.to_time
|
28
|
-
Dir.glob("#{SvelteOnRails::Configuration.instance.components_folder}**/*").each do |path|
|
29
|
-
if File.file?(path)
|
30
|
-
mtime = File.mtime(path)
|
31
|
-
if mtime > last_modification
|
32
|
-
last_modification = mtime
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
File.mtime(ts_file) < last_modification
|
37
|
-
|
38
|
-
elsif watch_changes
|
39
|
-
true
|
40
|
-
elsif !File.exist?(ts_file)
|
41
|
-
true
|
42
|
-
else
|
43
|
-
false
|
44
|
-
end
|
45
|
-
|
46
|
-
if have_changes || !File.exist?(compiled_js_file) || !File.exist?(compiled_css_file)
|
47
|
-
if have_changes || (!File.exist?(ts_file) && watch_changes)
|
48
|
-
self.class.reset_dist
|
49
|
-
end
|
50
|
-
compile
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def render_compiled_file(props = {})
|
55
|
-
require 'base64'
|
56
|
-
require 'json'
|
57
|
-
props_enc = Base64.strict_encode64(props.to_json).strip
|
58
|
-
cmd = [
|
59
|
-
'node',
|
60
|
-
'/Users/christian/projects-gmbh/gems/svelte-on-rails/svelte-on-rails-gem/lib/svelte_on_rails/render.js',
|
61
|
-
compiled_js_file,
|
62
|
-
props_enc,
|
63
|
-
SvelteOnRails::Configuration.instance.rails_root
|
64
|
-
].join(' ')
|
65
|
-
|
66
|
-
stdout, stderr, status = Open3.capture3(cmd, chdir: self.class.gem_app_dir)
|
67
|
-
unless status.to_s.match(/^pid [0-9]+ exit 0$/)
|
68
|
-
raise "Render Svelte Server-side =>\n#{cmd}\n\nError output from render.js (stderr) =>\n+++\n" + stderr + "+++\n\n"
|
69
|
-
end
|
70
|
-
|
71
|
-
begin
|
72
|
-
res = JSON.parse(stdout)
|
73
|
-
if File.exist?(compiled_css_file)
|
74
|
-
res['css'] = File.read(compiled_css_file)
|
75
|
-
end
|
76
|
-
return res
|
77
|
-
rescue JSON::ParserError => e
|
78
|
-
raise "Render Svelte Server-side: Expected JSON, got: «#{stdout}»"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def compiled_js_file
|
83
|
-
@compiled_file + '.js'
|
84
|
-
end
|
85
|
-
|
86
|
-
def compiled_css_file
|
87
|
-
@compiled_file + '.css'
|
88
|
-
end
|
89
|
-
|
90
|
-
def compile
|
91
|
-
|
92
|
-
start_time = Time.now
|
93
|
-
|
94
|
-
cnf = SvelteOnRails::Configuration.instance
|
95
|
-
subs = @svelte_filename.split('/')[0..-2].join('/')
|
96
|
-
dist = cnf.dist_folder + cnf.components_folder + subs
|
97
|
-
|
98
|
-
cmd = [
|
99
|
-
'node',
|
100
|
-
self.class.gem_app_dir + 'compile.js',
|
101
|
-
@svelte_file,
|
102
|
-
dist,
|
103
|
-
self.class.gem_app_dir
|
104
|
-
].join(' ')
|
105
|
-
|
106
|
-
stdout, stderr, status = Open3.capture3(cmd, chdir: SvelteOnRails::Configuration.instance.rails_root)
|
107
|
-
|
108
|
-
unless status.to_s.match(/^pid [0-9]+ exit 0$/)
|
109
|
-
raise "Compiling «#{@svelte_filename}» Server-side, script compile.js, executed within Rails.root:\n\n#{cmd}\n\n++++++\n\n#{stderr}\n\n++++++\n\n"
|
110
|
-
end
|
111
|
-
|
112
|
-
time = Time.now - start_time
|
113
|
-
Rails.logger.info " Compiled #{@svelte_filename}.js: #{time.round(3)}ms" rescue nil
|
114
|
-
end
|
115
|
-
|
116
|
-
def self.gem_app_dir
|
117
|
-
File.expand_path('../svelte_on_rails', __dir__) + '/'
|
118
|
-
end
|
119
|
-
|
120
|
-
def self.file_exist_case_sensitive?(containing_dir, filename)
|
121
|
-
# Combine the directory path and filename
|
122
|
-
full_path = File.join(containing_dir, filename)
|
123
|
-
|
124
|
-
# Check if the file exists and the path matches case-sensitively
|
125
|
-
File.exist?(full_path) && Dir[File.join(containing_dir, "**/*")].any? do |f|
|
126
|
-
f == full_path
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
# assets:precompile
|
131
|
-
def self.reset_dist
|
132
|
-
unless Dir.exist?(SvelteOnRails::Configuration.instance.dist_folder)
|
133
|
-
FileUtils.mkdir_p(SvelteOnRails::Configuration.instance.dist_folder)
|
134
|
-
end
|
135
|
-
FileUtils.rm_rf Dir.glob("#{SvelteOnRails::Configuration.instance.dist_folder}/*")
|
136
|
-
FileUtils.touch SvelteOnRails::Configuration.instance.dist_folder.join('reset_timestamp')
|
137
|
-
end
|
138
|
-
|
139
|
-
def self.reset_and_compile_all
|
140
|
-
SvelteOnRails::RenderServerSide.reset_dist
|
141
|
-
cnf = SvelteOnRails::Configuration.instance
|
142
|
-
frontend_folder = cnf.frontend_folder_full
|
143
|
-
sveltes = Dir.glob(cnf.frontend_folder_full.join('**/*.svelte'))
|
144
|
-
sveltes.each_with_index do |file, ind|
|
145
|
-
comp_name = file.to_s[(cnf.frontend_folder_full.to_s.length + 1)..-1]
|
146
|
-
|
147
|
-
n = SvelteOnRails::RenderServerSide.new(comp_name, base_path: frontend_folder)
|
148
|
-
n.compile
|
149
|
-
|
150
|
-
puts "compiled #{ind + 1}/#{sveltes.length}: #{comp_name}"
|
151
|
-
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
end
|
156
|
-
end
|