зеркало из
https://github.com/rs-pro/activeadmin-quill_editor.git
synced 2026-08-28 15:36:17 +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
|
||||
// This imports from vendor/assets/javascripts/activeadmin_quill_editor.js
|
||||
import QuillEditorModule from 'activeadmin_quill_editor';
|
||||
// This imports from vendor/assets/javascripts/activeadmin/quill_editor.js
|
||||
import QuillEditorModule from 'activeadmin/quill_editor';
|
||||
|
||||
// Now that Quill is available, initialize the editors
|
||||
// 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
|
||||
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
|
||||
|
||||
initializer 'activeadmin_quill_editor.assets' do |app|
|
||||
# For Propshaft (Rails 8 default)
|
||||
if defined?(Propshaft)
|
||||
# Add assets to precompile list for both Propshaft and Sprockets
|
||||
if app.config.respond_to?(:assets)
|
||||
app.config.assets.precompile += %w[
|
||||
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
|
||||
activeadmin/quill_editor.js
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2943,9 +2943,9 @@
|
||||
}
|
||||
});
|
||||
|
||||
// ../../vendor/assets/javascripts/activeadmin_quill_editor.js
|
||||
var require_activeadmin_quill_editor = __commonJS({
|
||||
"../../vendor/assets/javascripts/activeadmin_quill_editor.js"(exports2, module2) {
|
||||
// ../../vendor/assets/javascripts/activeadmin/quill_editor.js
|
||||
var require_quill_editor = __commonJS({
|
||||
"../../vendor/assets/javascripts/activeadmin/quill_editor.js"(exports2, module2) {
|
||||
(function() {
|
||||
"use strict";
|
||||
const defaultTheme = "snow";
|
||||
@@ -17117,7 +17117,7 @@ ${escapeText(this.code(index, length))}
|
||||
var quill_default = core_default;
|
||||
|
||||
// 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;
|
||||
try {
|
||||
const ImageUploader = __require("quill-image-uploader");
|
||||
@@ -17126,8 +17126,8 @@ ${escapeText(this.code(index, length))}
|
||||
}
|
||||
if (window.QuillEditor && window.QuillEditor.init) {
|
||||
window.QuillEditor.init();
|
||||
} else if (import_activeadmin_quill_editor.default && import_activeadmin_quill_editor.default.init) {
|
||||
import_activeadmin_quill_editor.default.init();
|
||||
} else if (import_quill_editor.default && import_quill_editor.default.init) {
|
||||
import_quill_editor.default.init();
|
||||
}
|
||||
})();
|
||||
/*! Bundled license information:
|
||||
|
||||
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
@@ -15,7 +15,7 @@ try {
|
||||
}
|
||||
|
||||
// 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
|
||||
// This ensures proper initialization order without setTimeout hacks
|
||||
|
||||
@@ -23,7 +23,7 @@ const config = {
|
||||
},
|
||||
// Use alias for clean imports
|
||||
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