зеркало из
https://github.com/rs-pro/activeadmin-quill_editor.git
synced 2026-09-06 03:35:50 +03:00
refactor: Remove jQuery dependency and consolidate JavaScript assets
- Rename vendor JS file to activeadmin/quill_editor.js to avoid conflicts - Update import alias to use 'activeadmin/quill_editor' for consistency - Remove jQuery-dependent legacy file (quill_editor_input.js) - Simplify engine asset configuration - only one JS file now - Update documentation with correct paths and import names - All functionality preserved with vanilla JavaScript BREAKING CHANGE: Drops support for jQuery-based initialization. Applications using the legacy jQuery initialization will need to update to the new module-based approach. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
Этот коммит содержится в:
@@ -1,123 +0,0 @@
|
|||||||
/* globals $ Quill ImageUploader */
|
|
||||||
(function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// --- functions ---------------------------------------------------------------
|
|
||||||
const initQuillEditors = () => {
|
|
||||||
const defaultTheme = 'snow';
|
|
||||||
const defaultToolbar = [
|
|
||||||
['bold', 'italic', 'underline'],
|
|
||||||
['link', 'blockquote', 'code-block'],
|
|
||||||
[{ 'script': 'sub' }, { 'script': 'super' }],
|
|
||||||
[{ 'align': [] }, { list: 'ordered' }, { list: 'bullet' }],
|
|
||||||
[{ 'color': [] }, { 'background': [] }],
|
|
||||||
['image'],
|
|
||||||
['clean'],
|
|
||||||
];
|
|
||||||
const editors = document.querySelectorAll('[data-aa-quill-editor]');
|
|
||||||
const registeredPlugins = {};
|
|
||||||
|
|
||||||
for (let i = 0; i < editors.length; i++) {
|
|
||||||
const content = editors[i].querySelector('[data-aa-quill-content]');
|
|
||||||
const isActive = editors[i].classList.contains('quill-editor--active');
|
|
||||||
|
|
||||||
if (content && !isActive) {
|
|
||||||
// Setup editor options
|
|
||||||
const options = editors[i].getAttribute('data-options') ? JSON.parse(editors[i].getAttribute('data-options')) : {};
|
|
||||||
|
|
||||||
if (!options.theme) options.theme = defaultTheme;
|
|
||||||
if (!options.modules) options.modules = {};
|
|
||||||
if (!options.modules.toolbar) options.modules.toolbar = defaultToolbar;
|
|
||||||
|
|
||||||
// Setup plugin options
|
|
||||||
const pluginOptions = editors[i].getAttribute('data-plugins') ? JSON.parse(editors[i].getAttribute('data-plugins')) : {};
|
|
||||||
|
|
||||||
if (pluginOptions.image_uploader && pluginOptions.image_uploader.server_url) {
|
|
||||||
if (!registeredPlugins.image_uploader) {
|
|
||||||
Quill.register('modules/imageUploader', ImageUploader);
|
|
||||||
registeredPlugins.image_uploader = true;
|
|
||||||
}
|
|
||||||
const opts = pluginOptions.image_uploader;
|
|
||||||
|
|
||||||
options.modules.imageUploader = setupImageUploader(opts.server_url, opts.field_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init editor
|
|
||||||
editors[i]['_quill-editor'] = new Quill(content, options);
|
|
||||||
editors[i].classList += ' quill-editor--active';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const formtastic = document.querySelector('form.formtastic');
|
|
||||||
|
|
||||||
if (formtastic) {
|
|
||||||
formtastic.onsubmit = () => {
|
|
||||||
for (let i = 0; i < editors.length; i++) {
|
|
||||||
const input = editors[i].querySelector('input[type="hidden"]');
|
|
||||||
|
|
||||||
if (editors[i]['_quill-editor'].editor.isBlank()) {
|
|
||||||
input.value = '';
|
|
||||||
} else {
|
|
||||||
input.value = editors[i]['_quill-editor'].root.innerHTML;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const setupImageUploader = (server_url, field_name) => {
|
|
||||||
return {
|
|
||||||
upload: (file) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const formData = new FormData();
|
|
||||||
|
|
||||||
formData.append(field_name || 'file_upload', file);
|
|
||||||
fetch(server_url, {
|
|
||||||
body: formData,
|
|
||||||
headers: {
|
|
||||||
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
|
||||||
},
|
|
||||||
method: 'POST'
|
|
||||||
}).then(response => response.json())
|
|
||||||
.then(result => {
|
|
||||||
if (!result.url) {
|
|
||||||
reject('Upload failed');
|
|
||||||
}
|
|
||||||
resolve(result.url);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
reject('Upload failed');
|
|
||||||
console.error('Error: ', error);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- public functions --------------------------------------------------------
|
|
||||||
window.getQuillEditors = function() {
|
|
||||||
const editors = document.querySelectorAll('[data-aa-quill-editor]');
|
|
||||||
const list = [];
|
|
||||||
|
|
||||||
editors.forEach(function(editor) { list.push(editor['_quill-editor']) });
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.getQuillEditorByIndex = function(index) {
|
|
||||||
const editors = document.querySelectorAll('[data-aa-quill-editor]');
|
|
||||||
|
|
||||||
return (index >= 0 && index < editors.length) ? editors[index]['_quill-editor'] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.getQuillEditorByElementId = function(id) {
|
|
||||||
const editor = document.querySelector(`[data-aa-quill-editor]#${id}`);
|
|
||||||
|
|
||||||
return editor ? editor['_quill-editor'] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- events ------------------------------------------------------------------
|
|
||||||
$(document).ready(initQuillEditors);
|
|
||||||
$(document).on('has_many_add:after', '.has_many_container', initQuillEditors);
|
|
||||||
$(document).on('turbolinks:load', initQuillEditors);
|
|
||||||
})();
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
# Session Summary - ActiveAdmin Quill Editor Modernization
|
|
||||||
|
|
||||||
## Context
|
|
||||||
We analyzed replacing Trumbowyg with Quill for ActiveAdmin 4.x and Rails 8 compatibility. After evaluating SunEditor (too large at 450KB after removing source maps) and Quill.js (~200KB), we chose to modernize the existing `activeadmin_quill_editor` gem.
|
|
||||||
|
|
||||||
## Important Discoveries
|
|
||||||
1. **Existing Test App**: The gem already has a full Rails test application at `spec/dummy/` (not using Combustion)
|
|
||||||
2. **Existing Tests**: Comprehensive system tests already exist in `spec/system/`
|
|
||||||
3. **Existing Formtastic Input**: `QuillEditorInput` class already exists, just needs jQuery removal
|
|
||||||
|
|
||||||
## Key Decisions Made
|
|
||||||
|
|
||||||
1. **Use Quill.js** instead of SunEditor
|
|
||||||
- Quill: ~200KB minified
|
|
||||||
- Clean delta-based architecture
|
|
||||||
- No jQuery dependency for the core library
|
|
||||||
- Existing gem foundation to build upon
|
|
||||||
|
|
||||||
2. **Serve assets directly from vendor/assets**
|
|
||||||
- No NPM package needed initially
|
|
||||||
- Propshaft automatically serves from vendor/assets and app/assets
|
|
||||||
- Simple drop-in integration
|
|
||||||
|
|
||||||
3. **Follow activeadmin_trumbowyg patterns**
|
|
||||||
- Combustion-based test app
|
|
||||||
- Modern CI with matrix testing (Ruby 3.3/3.4, Rails 7.x/8.x)
|
|
||||||
- Comprehensive GitHub Actions setup with caching
|
|
||||||
- ESBuild for test app assets
|
|
||||||
|
|
||||||
## Files Created
|
|
||||||
- `/data/activeadmin-quill_editor/docs/activeadmin-4-propshaft-update.md` - Complete migration guide
|
|
||||||
- `/data/activeadmin-quill_editor/docs/session-summary.md` - This summary
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
### Immediate Tasks
|
|
||||||
1. Download Quill 2.x assets and place in vendor/assets
|
|
||||||
2. Create new JavaScript initializer without jQuery
|
|
||||||
3. Update Formtastic input class (already exists, just needs updates)
|
|
||||||
4. Update existing spec/dummy test app for Propshaft/Rails 8
|
|
||||||
5. Configure GitHub Actions CI/CD
|
|
||||||
|
|
||||||
### Implementation Order
|
|
||||||
1. **Asset Setup** (vendor/assets structure)
|
|
||||||
2. **JavaScript Modernization** (remove jQuery)
|
|
||||||
3. **Test App Updates** (spec/dummy with Propshaft)
|
|
||||||
4. **CI/CD Setup** (GitHub Actions with matrix)
|
|
||||||
5. **Documentation Update** (README, examples)
|
|
||||||
|
|
||||||
### Testing Strategy
|
|
||||||
- Use existing spec/dummy Rails app (no Combustion needed)
|
|
||||||
- Update existing system tests, add missing cases from trumbowyg
|
|
||||||
- Matrix test against Ruby 3.3/3.4
|
|
||||||
- Test Rails 7.x and 8.x with ActiveAdmin 4.x beta
|
|
||||||
- Consider adding Playwright for modern browser tests
|
|
||||||
- SimpleCov for coverage with SonarQube integration
|
|
||||||
|
|
||||||
## Technical Notes
|
|
||||||
|
|
||||||
### Propshaft Asset Serving
|
|
||||||
- Gems can provide assets in `vendor/assets` and `app/assets`
|
|
||||||
- Propshaft automatically includes these paths in load path
|
|
||||||
- No compilation needed for vendored assets
|
|
||||||
- Digest stamping handled automatically
|
|
||||||
|
|
||||||
### JavaScript API Changes
|
|
||||||
Replace jQuery-based initialization:
|
|
||||||
```javascript
|
|
||||||
// Old (jQuery)
|
|
||||||
$(document).ready(initQuillEditors);
|
|
||||||
|
|
||||||
// New (Vanilla)
|
|
||||||
document.addEventListener('DOMContentLoaded', initQuillEditors);
|
|
||||||
document.addEventListener('turbo:load', initQuillEditors);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Form Input Usage
|
|
||||||
```ruby
|
|
||||||
f.input :content, as: :quill_editor, input_html: {
|
|
||||||
data: {
|
|
||||||
options: {
|
|
||||||
theme: 'snow',
|
|
||||||
modules: { toolbar: [...] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Resources
|
|
||||||
- Quill.js 2.x: https://quilljs.com/
|
|
||||||
- Propshaft docs: https://github.com/rails/propshaft
|
|
||||||
- Reference gems:
|
|
||||||
- /data/activeadmin_trumbowyg (modern CI/test setup)
|
|
||||||
- /data/activeadmin-searchable_select (alternative patterns)
|
|
||||||
|
|
||||||
## Contact for Questions
|
|
||||||
Review the comprehensive guide at `activeadmin-4-propshaft-update.md` for complete implementation details.
|
|
||||||
@@ -63,8 +63,8 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Import the Quill Editor initialization module from the gem
|
// Import the Quill Editor initialization module from the gem
|
||||||
// This imports from vendor/assets/javascripts/activeadmin_quill_editor.js
|
// This imports from vendor/assets/javascripts/activeadmin/quill_editor.js
|
||||||
import QuillEditorModule from 'activeadmin_quill_editor';
|
import QuillEditorModule from 'activeadmin/quill_editor';
|
||||||
|
|
||||||
// Now that Quill is available, initialize the editors
|
// Now that Quill is available, initialize the editors
|
||||||
// This ensures proper initialization order without setTimeout hacks
|
// This ensures proper initialization order without setTimeout hacks
|
||||||
@@ -130,7 +130,7 @@ const config = {
|
|||||||
},
|
},
|
||||||
// CRITICAL: Use alias to import the gem's JavaScript from vendor/assets
|
// CRITICAL: Use alias to import the gem's JavaScript from vendor/assets
|
||||||
alias: {
|
alias: {
|
||||||
'activeadmin_quill_editor': path.join(gemPath, 'vendor/assets/javascripts/activeadmin_quill_editor.js')
|
'activeadmin/quill_editor': path.join(gemPath, 'vendor/assets/javascripts/activeadmin/quill_editor.js')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,16 +11,10 @@ module ActiveAdmin
|
|||||||
# No need for explicit asset path configuration with Propshaft
|
# No need for explicit asset path configuration with Propshaft
|
||||||
|
|
||||||
initializer 'activeadmin_quill_editor.assets' do |app|
|
initializer 'activeadmin_quill_editor.assets' do |app|
|
||||||
# For Propshaft (Rails 8 default)
|
# Add assets to precompile list for both Propshaft and Sprockets
|
||||||
if defined?(Propshaft)
|
if app.config.respond_to?(:assets)
|
||||||
app.config.assets.precompile += %w[
|
app.config.assets.precompile += %w[
|
||||||
activeadmin_quill_editor.js
|
activeadmin/quill_editor.js
|
||||||
]
|
|
||||||
# For Sprockets (legacy support)
|
|
||||||
elsif app.config.respond_to?(:assets)
|
|
||||||
app.config.assets.precompile += %w[
|
|
||||||
activeadmin/quill_editor_input.js
|
|
||||||
activeadmin_quill_editor.js
|
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2943,9 +2943,9 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ../../vendor/assets/javascripts/activeadmin_quill_editor.js
|
// ../../vendor/assets/javascripts/activeadmin/quill_editor.js
|
||||||
var require_activeadmin_quill_editor = __commonJS({
|
var require_quill_editor = __commonJS({
|
||||||
"../../vendor/assets/javascripts/activeadmin_quill_editor.js"(exports2, module2) {
|
"../../vendor/assets/javascripts/activeadmin/quill_editor.js"(exports2, module2) {
|
||||||
(function() {
|
(function() {
|
||||||
"use strict";
|
"use strict";
|
||||||
const defaultTheme = "snow";
|
const defaultTheme = "snow";
|
||||||
@@ -17117,7 +17117,7 @@ ${escapeText(this.code(index, length))}
|
|||||||
var quill_default = core_default;
|
var quill_default = core_default;
|
||||||
|
|
||||||
// app/javascript/active_admin.js
|
// app/javascript/active_admin.js
|
||||||
var import_activeadmin_quill_editor = __toESM(require_activeadmin_quill_editor());
|
var import_quill_editor = __toESM(require_quill_editor());
|
||||||
window.Quill = quill_default;
|
window.Quill = quill_default;
|
||||||
try {
|
try {
|
||||||
const ImageUploader = __require("quill-image-uploader");
|
const ImageUploader = __require("quill-image-uploader");
|
||||||
@@ -17126,8 +17126,8 @@ ${escapeText(this.code(index, length))}
|
|||||||
}
|
}
|
||||||
if (window.QuillEditor && window.QuillEditor.init) {
|
if (window.QuillEditor && window.QuillEditor.init) {
|
||||||
window.QuillEditor.init();
|
window.QuillEditor.init();
|
||||||
} else if (import_activeadmin_quill_editor.default && import_activeadmin_quill_editor.default.init) {
|
} else if (import_quill_editor.default && import_quill_editor.default.init) {
|
||||||
import_activeadmin_quill_editor.default.init();
|
import_quill_editor.default.init();
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
/*! Bundled license information:
|
/*! Bundled license information:
|
||||||
|
|||||||
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
@@ -15,7 +15,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Import the Quill Editor initialization module
|
// Import the Quill Editor initialization module
|
||||||
import QuillEditorModule from 'activeadmin_quill_editor';
|
import QuillEditorModule from 'activeadmin/quill_editor';
|
||||||
|
|
||||||
// Now that Quill is available, initialize the editors
|
// Now that Quill is available, initialize the editors
|
||||||
// This ensures proper initialization order without setTimeout hacks
|
// This ensures proper initialization order without setTimeout hacks
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const config = {
|
|||||||
},
|
},
|
||||||
// Use alias for clean imports
|
// Use alias for clean imports
|
||||||
alias: {
|
alias: {
|
||||||
'activeadmin_quill_editor': path.join(gemPath, 'vendor/assets/javascripts/activeadmin_quill_editor.js')
|
'activeadmin/quill_editor': path.join(gemPath, 'vendor/assets/javascripts/activeadmin/quill_editor.js')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user