116 Коммитов

Автор SHA1 Сообщение Дата
Mattia Roccoberton
7d3a084977 Merge pull request #56 from blocknotes/v1.3.0
chore: Bump to version 1.3.0
2025-03-18 22:25:05 +01:00
Mattia Roccoberton
1569b1ff18 chore: Bump to version 1.3.0 2025-03-18 22:15:04 +01:00
Mattia Roccoberton
3459800dbf Merge pull request #55 from blocknotes/api/quill-editor-query-functions
API: Quill editor query functions
2025-03-18 08:49:00 +01:00
Mattia Roccoberton
af901f4f7d feat: API: expose quill editor query functions 2025-03-18 08:47:16 +01:00
Mattia Roccoberton
328ee0d9fa Merge pull request #54 from blocknotes/test/update-test-suite-2
test: Update test suite (2)
2025-03-17 09:08:23 +01:00
Mattia Roccoberton
751196ef8c test: Update dependencies 2025-03-17 09:06:04 +01:00
Mattia Roccoberton
589b782866 Merge pull request #53 from blocknotes/test/update-test-suite
test: Update test suite
2025-03-17 08:46:08 +01:00
Mattia Roccoberton
554f6086e7 test: Add Rails 8.0 workflow 2025-03-17 08:44:22 +01:00
Mattia Roccoberton
051ada9843 test: Add Rails 7.2 workflow 2025-03-17 08:35:44 +01:00
Mattia Roccoberton
fd90851a6b test: Update ruby versions in specs workflows 2025-03-17 08:30:59 +01:00
Mattia Roccoberton
bd32c5f28f Merge pull request #52 from blocknotes/test/improve-specs
test: Improve specs using page objects
2025-03-16 18:30:55 +01:00
Mattia Roccoberton
21ec7a918b chore: Update Rubocop config 2025-03-16 18:29:42 +01:00
Mattia Roccoberton
b310f9e71b test: Improve specs using page objects 2025-03-16 18:29:42 +01:00
Mattia Roccoberton
bbee6f7681 Merge pull request #51 from blocknotes/dev/docker-setup-2
Update Docker dev setup
2025-03-16 11:07:57 +01:00
Mattia Roccoberton
57e151aa03 test: Fix ProcessTimeoutError when using Docker
- Error details:

Ferrum::ProcessTimeoutError:
  Browser did not produce websocket url within 10 seconds, try to increase `:process_timeout`

- Reference issue: https://github.com/rubycdp/cuprite/issues/180
2025-03-16 11:05:57 +01:00
Mattia Roccoberton
0913bb6915 chore: Update Docker dev setup 2025-03-16 11:05:57 +01:00
Mattia Roccoberton
728e3fa097 Merge pull request #50 from blocknotes/dev/docker-setup
chore: Docker dev setup
2025-03-14 15:57:12 +01:00
Mattia Roccoberton
9d891f0602 chore: Docker dev setup 2025-03-14 15:54:58 +01:00
Mattia Roccoberton
21fc69c2c0 Merge pull request #49 from blocknotes/mat/update-github-actions
Update Github actions
2025-03-09 15:36:22 +01:00
Mattia Roccoberton
b0e770ca9e ci: update Github actions 2025-03-09 15:28:46 +01:00
Mattia Roccoberton
ba53f9febf Merge pull request #47 from Shyrokonis/main
Add check to prevent GET request for non-existent image after upload
2025-03-09 09:17:33 +01:00
Dmytro Shyrokonis
d690b9906f [Fix] Add reject for nil result url 2024-11-12 16:22:31 +01:00
Mattia Roccoberton
99908f97f7 Merge pull request #45 from blocknotes/chore/bump-to-version-1.2.0
chore: bump to version 1.2.0
2024-02-29 17:08:52 +01:00
Mattia Roccoberton
9389f9e32d chore: bump to version 1.2.0 2024-02-29 17:07:32 +01:00
Mattia Roccoberton
4629ac4133 Merge pull request #44 from blocknotes/doc/update-readme
doc: update README
2024-02-29 17:04:06 +01:00
Mattia Roccoberton
0d4485c321 doc: update readme 2024-02-29 17:03:10 +01:00
Mattia Roccoberton
0c1cfefa83 Merge pull request #43 from blocknotes/test/update-test-suite-config
test: update test suite config
2024-02-26 09:16:55 +01:00
Mattia Roccoberton
0c674025a9 test: update test suite config 2024-02-26 09:15:38 +01:00
Mattia Roccoberton
770e069442 Merge pull request #42 from blocknotes/refactor/update-minimum-ruby-version
refactor: update minimum Ruby version to 3.0
2024-02-25 16:11:37 +01:00
Mattia Roccoberton
d346729cd1 build: update Appraisals dependencies 2024-02-25 16:08:53 +01:00
Mattia Roccoberton
ce65cfbb7e refactor!: update minimum Ruby version to 3.0 2024-02-25 16:08:50 +01:00
Mattia Roccoberton
22a1c8714c Merge pull request #41 from blocknotes/chore/rename-master-branch-to-main
chore: rename master branch to main
2024-02-25 11:50:30 +01:00
Mattia Roccoberton
489e1c35eb chore: rename master branch to main 2024-02-25 11:46:50 +01:00
Mattia Roccoberton
62efca80d6 chore: bump to version 1.1.0 2023-08-20 21:37:32 +02:00
Mattia Roccoberton
46168cc7f8 Merge pull request #38 from blocknotes/chore/update-ci-config
chore: update tests config
2023-08-20 21:27:50 +02:00
Mattia Roccoberton
02310804aa chore: add Overcommit config 2023-08-20 21:23:48 +02:00
Mattia Roccoberton
7e2f8733dc chore: update CI ruby versions 2023-08-20 21:23:46 +02:00
Mattia Roccoberton
2d0a8f961f chore: update tests config 2023-08-20 21:11:30 +02:00
Mattia Roccoberton
7262ad5523 Merge pull request #36 from alejandroperea/allow-active-admin-3
Allow ActiveAdmin 3
2023-08-20 20:08:39 +02:00
Alejandro Perea
71f227736d Update Appraisal gemfiles 2023-08-20 17:53:02 +02:00
Mattia Roccoberton
361da5096d Update activeadmin_quill_editor.gemspec
I'm going on with the proposed changes to speed up the PR
2023-08-20 16:13:24 +02:00
Alejandro Perea
17ef9aa5db Allow ActiveAdmin 3 2023-08-13 11:57:03 +02:00
Mattia Roccoberton
b00fcd90ab Add rspec-retry gem 2022-04-19 22:07:02 +02:00
Mattia Roccoberton
edf5cbcb13 Merge pull request #30 from blocknotes/minor-improvements
v1.0.0
2022-04-19 21:55:07 +02:00
Mattia Roccoberton
38e5406d5d Bump to version 1.0.0 2022-04-19 21:49:20 +02:00
Mattia Roccoberton
c560dd5c60 Changelog update 2022-04-19 21:49:20 +02:00
Mattia Roccoberton
597cae7adb Test the Quill JS presence and version 2022-04-19 21:49:20 +02:00
Mattia Roccoberton
6d0599c39e Minor improvements 2022-04-19 21:49:20 +02:00
Mattia Roccoberton
664765ac79 Remove unused gems 2022-04-19 21:49:20 +02:00
Mattia Roccoberton
7be390701f Enable Rails 7.0 specs support 2022-04-19 21:49:20 +02:00
Mattia Roccoberton
e4401a469b Enable Ruby 3.0 specs support 2022-04-19 21:49:20 +02:00
Mattia Roccoberton
d8632f069a Setup Cuprite 2022-04-19 21:49:20 +02:00
Mattia Roccoberton
7498cd65a1 Setup Appraisal 2022-03-29 19:42:43 +02:00
Mattia Roccoberton
038d66f387 Set minimum Ruby version to 2.6.0 and enable MFA 2022-03-26 18:04:33 +01:00
Mattia Roccoberton
7af25106a2 Remove sassc dependency 2022-03-26 18:00:12 +01:00
Mattia Roccoberton
d021f3650e README update 2022-03-26 17:54:26 +01:00
Mattia Roccoberton
8a13dd49a4 Create FUNDING.yml 2022-03-18 18:42:18 +01:00
Mattia Roccoberton
1cad5a10c3 Merge pull request #26 from blocknotes/update-linters-config
Update linters config
2021-07-10 15:41:05 +02:00
Mattia Roccoberton
63b4c118f6 Update linters config 2021-07-10 15:34:00 +02:00
Mattia Roccoberton
277d1a521a Merge pull request #24 from blocknotes/github_actions_improvements2
Add linter workflow
2021-06-02 15:53:24 +02:00
Mattia Roccoberton
4a0ea5e8f2 Add linter workflow 2021-06-02 15:52:19 +02:00
Mattia Roccoberton
ffc57e7d90 Badge for gem downloads 2021-05-23 22:48:09 +02:00
Mattia Roccoberton
2ebc9176b4 Merge pull request #23 from blocknotes/github_actions_improvements
GitHub Actions improvements
2021-05-23 21:23:19 +02:00
Mattia Roccoberton
0b44c683e6 GitHub Actions improvements 2021-05-23 14:51:28 +02:00
Mattia Roccoberton
9b460d36e3 Minor specs changes 2021-05-23 14:23:19 +02:00
Mattia Roccoberton
d41f8450ea Move some dependencies to the Gemfile 2021-05-23 14:22:28 +02:00
Mattia Roccoberton
401d2528e8 Merge pull request #22 from blocknotes/setup_github_actions_specs
Update GitHub Actions
2021-05-13 23:01:05 +02:00
Mattia Roccoberton
e086bac0a7 Update README 2021-05-13 22:59:41 +02:00
Mattia Roccoberton
36cd836ca8 Remove CircleCI config 2021-05-13 22:57:46 +02:00
Mattia Roccoberton
c05666673e Update GitHub Actions 2021-05-13 22:24:14 +02:00
Mattia Roccoberton
2d5429718c Bump to version 0.3.4 2021-03-16 08:32:57 +01:00
Mattia Roccoberton
78126d0cd7 Fix editor loading with Turbolinks 2021-03-14 16:05:21 +01:00
Mattia Roccoberton
3190134973 Small update to the README 2021-03-14 15:42:14 +01:00
Mattia Roccoberton
8d6b05297a Bump to version 0.3.2 2021-03-14 15:30:59 +01:00
Mattia Roccoberton
5d9b6f70fd Improve specs
- Add test examples for bold and italic content
- Move some test examples
- Adjust RSpec options
2021-03-14 15:26:24 +01:00
Mattia Roccoberton
6fa021c0c7 Update README 2021-03-14 14:35:51 +01:00
Mattia Roccoberton
357ef382d6 Update dependencies to test on Rails 6.1 2021-03-14 12:44:55 +01:00
Mattia Roccoberton
43ae70c7c9 Update NPM package files list 2020-10-06 22:37:25 +02:00
Mattia Roccoberton
6daf6f6bc8 Set word-break: break-all to prevent editor overflow 2020-10-06 22:30:16 +02:00
Mattia Roccoberton
98c235d346 Create brakeman-analysis.yml 2020-10-01 22:22:41 +02:00
Mattia Roccoberton
e6e6742753 Merge pull request #15 from blocknotes/feature/webpacker-support
Webpacker support
2020-10-01 07:56:57 +02:00
Mattia Roccoberton
c2c8d48795 Webpacker support 2020-10-01 07:56:03 +02:00
Mattia Roccoberton
72062c1a30 v0.2.14 2020-09-10 07:40:35 +02:00
Mattia Roccoberton
c4aa91225b Minor specs improvement 2020-09-09 12:58:14 +02:00
Mattia Roccoberton
3cc6edb302 JS strict directive 2020-09-09 07:48:45 +02:00
Mattia Roccoberton
d78fb2eb9c v0.2.12 2020-09-08 18:35:23 +02:00
Mattia Roccoberton
e5db64af96 JS refactoring 2020-09-08 18:26:24 +02:00
Mattia Roccoberton
c0d37ad94e v0.2.10 2020-09-05 16:08:46 +02:00
Mattia Roccoberton
96c70106a4 Add a new example: upload plugin using Active Storage 2020-09-05 16:07:19 +02:00
Mattia Roccoberton
4ec6e80760 Editor default options refactoring + include imageUploader plugin
In order to use imageUploader plugin:
- js/css files must included in the app;
- an upload method must be provided in Active Admin entity;
- the image_uploader server_url field option needs to be set.
2020-09-04 10:53:29 +02:00
Mattia Roccoberton
707f4a5cc7 README improvements 2020-09-04 09:14:18 +02:00
Mattia Roccoberton
dc97316303 v0.2.9 2020-09-04 08:49:20 +02:00
Mattia Roccoberton
e9b8abc88e Merge pull request #14 from blocknotes/fix/text-alignment
Reduce the importance of the reset rules
2020-09-03 13:02:47 +02:00
Mattia Roccoberton
582667dc59 Reduce the importance of the reset rules
This allows to let Quill features to override the reset styles.

Closes #8
2020-09-03 13:00:42 +02:00
m.pestov
76c06f5346 Don't send paragraph tag if editor blank 2020-09-03 12:45:42 +02:00
Mattia Roccoberton
4e20e658ac v0.2.8 2020-09-03 11:53:48 +02:00
Mattia Roccoberton
135a56dc03 Add specs for editor in nested resources 2020-09-03 11:50:23 +02:00
Mattia Roccoberton
668bd642e5 Add Rubocop 2020-09-03 11:26:54 +02:00
Mattia Roccoberton
ab8c4fd73f Remove SimpleCov 2020-09-03 11:24:55 +02:00
Mattia Roccoberton
d60ed0f723 Update screenshot 2020-09-03 11:20:35 +02:00
Mattia Roccoberton
98b29d6f69 Minor style improvements 2020-09-03 11:20:12 +02:00
Mattia Roccoberton
962b48bb30 README improvements 2020-09-01 11:48:47 +02:00
Mattia Roccoberton
03b2d0e4e8 Merge pull request #13 from blocknotes/circleci-project-setup
Add CircleCI setup
2020-09-01 11:45:00 +02:00
Mattia Roccoberton
593ad3841a Add .circleci/config.yml 2020-09-01 11:40:23 +02:00
Mattia Roccoberton
d96162fedd v0.2.4 2020-09-01 11:31:12 +02:00
Mattia Roccoberton
a43a4ff0ba Add minimum specs 2020-09-01 11:17:38 +02:00
Mattia Roccoberton
7a148c7cd1 Add specs configuration 2020-09-01 11:16:56 +02:00
Mattia Roccoberton
5c462f5d7c Update Quill editor to version 1.3.7 2020-09-01 11:05:48 +02:00
Mattia Roccoberton
9ecfceaa9a 🎉 Support ActiveAdmin 2.x and code style improvements
- Add support ActiveAdmin for 2.x
- Add rubocop config
- Add frozen_string_literal to ruby files
- Apply changes to respect rubocop alerts
2019-06-15 19:55:45 +02:00
Mattia Roccoberton
598b2d75cf Merge pull request #6 from seanfcarroll/patch-1
Correct Quill options list link
2018-11-24 17:37:57 +01:00
Sean
54026744c4 Correct Quill options list link 2018-11-16 13:39:41 +01:00
mat@blocknot.es
5d35feedd8 v0.1.4: PR4 + Quill Editor 1.3.6 2018-11-03 18:44:54 +01:00
Mattia Roccoberton
73ee9e3787 Merge pull request #4 from mylescc/master
Thank you @mylescc
2018-11-03 17:07:30 +01:00
Myles Cowper-Coles
b251a28b13 Making sure quill editor updates with has_many
What:

* adding an event listerner so when people add a 'has_many' relationship
the quill editor is initialized correctly on any fields;

Why:

* If you have a nested has_many attributes in active admin, the form
is not created until you click the 'Add New ObjectName' button. This
triggers a jQuery event called 'has_many_add:after' which you can use to
trigger the re init of the quill editor.
* 9a33a081c9/app/assets/javascripts/active_admin/lib/has_many.es6 (L52)
2018-09-25 14:57:33 +01:00
Mattia Roccoberton
d3f2191843 Fix data-options lookup when multiple editors exist. 2018-04-02 09:12:39 +02:00
Mattia Roccoberton
0dfb48aec2 Merge pull request #2 from bcipriano/fix-multi-data-options
Fix data-options lookup when multiple editors exist.
2018-04-02 09:09:28 +02:00
123 изменённых файлов: 25695 добавлений и 25979 удалений

2
.env Обычный файл
Просмотреть файл

@@ -0,0 +1,2 @@
UID=1000
GID=1000

102
.github/workflows/ci.yml поставляемый
Просмотреть файл

@@ -1,102 +0,0 @@
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
ruby: ['3.0', '3.1', '3.2', '3.3']
gemfile:
- rails_6.1_active_admin_2.9
- rails_7.0_active_admin_2.x
- rails_7.0_active_admin_3.x
- rails_7.1_active_admin_3.x
- rails_7.2_active_admin_3.x
- rails_7.2_active_admin_4.x
- rails_8.0_active_admin_4.x
exclude:
# Rails 8 requires Ruby 3.2+
- ruby: '3.0'
gemfile: rails_8.0_active_admin_4.x
- ruby: '3.1'
gemfile: rails_8.0_active_admin_4.x
# ActiveAdmin 4 requires Ruby 3.2+
- ruby: '3.0'
gemfile: rails_7.2_active_admin_4.x
- ruby: '3.1'
gemfile: rails_7.2_active_admin_4.x
env:
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
RAILS_ENV: test
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: spec/dummy/package-lock.json
- name: Install npm dependencies for dummy app
run: |
cd spec/dummy
npm install
- name: Build assets for dummy app
run: |
cd spec/dummy
# Build JavaScript with esbuild
npm run build:js || true
# Build CSS with Tailwind for AA4
if [[ "${{ matrix.gemfile }}" == *"4.x"* ]]; then
npm run build:css || true
fi
- name: Database setup
run: |
cd spec/dummy
bundle exec rails db:create db:migrate db:test:prepare
- name: Run tests
run: bundle exec rspec --format progress
- name: Upload screenshots on failure
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-screenshots-${{ matrix.ruby }}-${{ matrix.gemfile }}
path: spec/dummy/tmp/capybara
if-no-files-found: ignore
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
bundler-cache: true
- name: Run RuboCop
run: bundle exec rubocop --force-exclusion

35
.github/workflows/linters.yml поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,35 @@
---
name: Linters
on:
push:
branches:
- main
pull_request:
jobs:
reviewdog:
name: reviewdog
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- uses: reviewdog/action-setup@v1
with:
reviewdog_version: latest
- name: Run reviewdog
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
reviewdog -fail-on-error -reporter=github-pr-review -runners=fasterer,rubocop
# NOTE: check with: reviewdog -fail-on-error -reporter=github-pr-review -runners=fasterer -diff="git diff" -tee

42
.github/workflows/specs_rails61.yml поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,42 @@
---
name: Specs Rails 6.1
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.2']
gemfile: ['rails61_activeadmin29', 'rails61_activeadmin']
env:
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run tests
run: bundle exec rspec --profile
- name: On failure, archive screenshots as artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-failed-screenshots
path: spec/dummy/tmp/screenshots

42
.github/workflows/specs_rails70.yml поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,42 @@
---
name: Specs Rails 7.0
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.3']
gemfile: ['rails70_activeadmin']
env:
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run tests
run: bundle exec rspec --profile
- name: On failure, archive screenshots as artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-failed-screenshots
path: spec/dummy/tmp/screenshots

42
.github/workflows/specs_rails71.yml поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,42 @@
---
name: Specs Rails 7.1
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.2', '3.4']
gemfile: ['rails71_activeadmin']
env:
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run tests
run: bundle exec rspec --profile
- name: On failure, archive screenshots as artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-failed-screenshots
path: spec/dummy/tmp/screenshots

42
.github/workflows/specs_rails72.yml поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,42 @@
---
name: Specs Rails 7.2
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.2', '3.4']
gemfile: ['rails72_activeadmin']
env:
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run tests
run: bundle exec rspec --profile
- name: On failure, archive screenshots as artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-failed-screenshots
path: spec/dummy/tmp/screenshots

42
.github/workflows/specs_rails80.yml поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,42 @@
---
name: Specs Rails 8.0
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.2', '3.4']
gemfile: ['rails80_activeadmin']
env:
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run tests
run: bundle exec rspec --profile
- name: On failure, archive screenshots as artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-failed-screenshots
path: spec/dummy/tmp/screenshots

5
.gitignore поставляемый
Просмотреть файл

@@ -6,12 +6,7 @@
/Gemfile.lock
/_misc/
/coverage/
/spec/dummy/db/*.sqlite3*
/spec/dummy/db/schema-dev.rb
/spec/dummy/log/
/spec/dummy/storage/
/spec/dummy/tmp/
tmp/
/spec/dummy/node_modules/
/gemfiles/*.gemfile.lock

Просмотреть файл

@@ -1,70 +1,31 @@
---
inherit_from:
- https://relaxed.ruby.style/rubocop.yml
plugins:
- rubocop-capybara
- rubocop-packaging
- rubocop-performance
- rubocop-rails
- rubocop-rspec
- rubocop-rspec_rails
inherit_mode:
merge:
- Exclude
require:
- rubocop-packaging
AllCops:
NewCops: enable
TargetRubyVersion: 3.0
SuggestExtensions: false
DisplayCopNames: true
CacheRootDirectory: tmp/rubocop-cache
Exclude:
- bin/*
- coverage/**/*
- db/schema.rb
- docs/**/*
- examples/**/*
- gemfiles/**/*
- spec/dummy/**/*
- vendor/**/*
Layout/LineLength:
Max: 120
Metrics/BlockLength:
Enabled: true
Exclude:
- spec/**/*
- docs/**/*
Metrics/MethodLength:
Max: 20
Exclude:
- spec/**/*
Style/Documentation:
Enabled: false
Style/StringLiterals:
EnforcedStyle: single_quotes
Style/StringLiteralsInInterpolation:
EnforcedStyle: double_quotes
NewCops: enable
TargetRubyVersion: 3.0
RSpec/ExampleLength:
# default 5
Max: 12
Exclude:
- spec/system/**/*
RSpec/MultipleExpectations:
# default 1
Max: 4
Exclude:
- spec/system/**/*
RSpec/MultipleMemoizedHelpers:
Max: 10
Rails/SkipsModelValidations:
Enabled: true
Rails/ActiveRecordAliases:
Enabled: true

1
.tool-versions Обычный файл
Просмотреть файл

@@ -0,0 +1 @@
ruby 3.4.2

Просмотреть файл

@@ -1,19 +0,0 @@
# Repository Guidelines
## Project Structure & Module Organization
The gem code lives in `lib/activeadmin` and `lib/formtastic`, with the public entry point in `lib/activeadmin_quill_editor.rb`. Ruby assets and templates that Active Admin mounts ship from `app/assets` and `app/views`. Front-end bundles exposed to consuming apps sit in `index.js` and the `app/assets/javascripts/activeadmin/quill_editor` tree. System specs exercise the dummy Rails app under `spec/dummy`, while reusable page helpers reside in `spec/page_objects`.
## Build, Test, and Development Commands
`make up` builds the Docker environment defined in `extra/docker-compose.yml` and prepares the dummy app; add `RUBY`, `RAILS`, or `ACTIVEADMIN` env vars to test matrix combinations. Run `make specs` (or directly `bin/rspec --fail-fast`) to execute the suite, and `make lint` to invoke `bin/rubocop` inside the container. Use `make shell` for interactive debugging and `make server` to boot the dummy Rails instance at `SERVER_PORT`.
## Coding Style & Naming Conventions
Follow the `.rubocop.yml` rules: two-space indentation, trailing commas on multiline literals, double quotes where interpolation occurs, and `snake_case` for Ruby identifiers. Use `CamelCase` for classes and modules under the `ActiveadminQuillEditor` namespace, mirroring existing files. JavaScript additions in `app/assets/javascripts` should align with the lintable ES module style in `index.js`; run `npx eslint index.js` if you modify the package entry point.
## Testing Guidelines
RSpec powers the suite; place feature-level coverage in `spec/system`, supporting components in `spec/page_objects`, and pure Ruby behaviour in `spec`. Prefer descriptive example names (`it "renders toolbar buttons"`) and keep factories in the dummy app to mirror real usage. Start tests with `make specs`; use `bin/rspec spec/system/editor_spec.rb` to target a file.
## Commit & Pull Request Guidelines
Recent history follows conventional prefixes (`fix:`, `ci:`, `chore:`); keep messages in the imperative mood and limit the subject to 72 characters. Every pull request should link related GitHub issues, summarize user-facing changes, and note any docs or assets touched. Include screenshots or GIFs when altering the editor UI, and confirm that both `make specs` and `make lint` pass in the PR description. Request review from a maintainer and re-run the pipeline after rebases.
## Security & Configuration Tips
Store local-only overrides in `extra/.env` (kept out of version control) and avoid committing credentials to the dummy app. The docker-compose services mount the repository directly, so prefer editing files via your host editor rather than inside the container to prevent permission drift.

Просмотреть файл

@@ -1,67 +1,33 @@
# frozen_string_literal: true
# Rails 6.1 with ActiveAdmin 2.9
appraise 'rails-6.1-active-admin-2.9' do
gem 'rails', '~> 6.1.0'
appraise 'rails61-activeadmin29' do
gem 'activeadmin', '~> 2.9.0'
gem 'sassc'
gem 'sprockets-rails'
remove_gem 'propshaft'
remove_gem 'importmap-rails'
gem 'rails', '~> 6.1.0'
end
# Rails 7.0 with ActiveAdmin 2.x
appraise 'rails-7.0-active-admin-2.x' do
appraise 'rails61-activeadmin' do
gem 'activeadmin'
gem 'rails', '~> 6.1.0'
end
appraise 'rails70-activeadmin' do
gem 'activeadmin'
gem 'rails', '~> 7.0.0'
gem 'activeadmin', '~> 2.14'
gem 'sassc'
gem 'sprockets-rails'
remove_gem 'propshaft'
remove_gem 'importmap-rails'
gem 'sqlite3', '~> 1.3'
end
# Rails 7.0 with ActiveAdmin 3.x
appraise 'rails-7.0-active-admin-3.x' do
gem 'rails', '~> 7.0.0'
gem 'activeadmin', '~> 3.2'
gem 'sassc'
gem 'sprockets-rails'
remove_gem 'propshaft'
remove_gem 'importmap-rails'
end
# Rails 7.1 with ActiveAdmin 3.x
appraise 'rails-7.1-active-admin-3.x' do
appraise 'rails71-activeadmin' do
gem 'activeadmin'
gem 'rails', '~> 7.1.0'
gem 'activeadmin', '~> 3.2'
gem 'sassc'
gem 'sprockets-rails'
remove_gem 'propshaft'
remove_gem 'importmap-rails'
end
# Rails 7.2 with ActiveAdmin 3.x
appraise 'rails-7.2-active-admin-3.x' do
appraise 'rails72-activeadmin' do
gem 'activeadmin'
gem 'rails', '~> 7.2.0'
gem 'activeadmin', '~> 3.2'
gem 'sassc'
gem 'sprockets-rails'
remove_gem 'propshaft'
remove_gem 'importmap-rails'
end
# Rails 7.2 with ActiveAdmin 4.x beta
appraise 'rails-7.2-active-admin-4.x' do
gem 'rails', '~> 7.2.0'
gem 'activeadmin', '4.0.0.beta16'
gem 'importmap-rails'
gem 'propshaft'
end
# Rails 8.0 with ActiveAdmin 4.x beta
appraise 'rails-8.0-active-admin-4.x' do
appraise 'rails80-activeadmin' do
gem 'activeadmin'
gem 'rails', '~> 8.0.0'
gem 'activeadmin', '4.0.0.beta16'
gem 'importmap-rails'
gem 'propshaft'
end

Просмотреть файл

@@ -2,10 +2,6 @@
An Active Admin plugin to use Quill Rich Text Editor.
## v2.0.0 - 2025-04-15
- Update Quill from 1.3.7 to 2.0.3
## v1.3.0 - 2025-03-18
- Javascript API: expose Quill editor query functions

77
Gemfile
Просмотреть файл

@@ -2,80 +2,38 @@
source 'https://rubygems.org'
def eval_version(dependency, version)
return [dependency] if version.empty?
# Handle versions that already have operators like ~>, >=, etc.
if version.match?(/^[~<>=]/)
[dependency, version]
else
# Add ~> operator and ensure version has at least 2 dots
version.count('.') < 2 ? [dependency, "~> #{version}.0"] : [dependency, "~> #{version}"]
end
end
if ENV['DEVEL'] == '1'
# for Docker dev
rails_ver = ENV.fetch('RAILS_VERSION')
gem 'rails', rails_ver
gem 'activeadmin', ENV.fetch('ACTIVEADMIN_VERSION')
gem 'activeadmin_quill_editor', path: './'
if rails_ver.start_with?('7.0')
gem 'concurrent-ruby', '1.3.4'
gem 'sqlite3', '~> 1.4'
else
gem 'sqlite3'
end
else
gemspec
gem 'sqlite3'
end
ruby_ver = ENV.fetch('RUBY_VERSION', '')
rails_ver = ENV.fetch('RAILS_VERSION', '')
rails = eval_version('rails', rails_ver)
gem(*rails)
active_admin_ver = ENV.fetch('ACTIVEADMIN_VERSION', '')
active_admin_requirement =
if active_admin_ver.empty?
'~> 4.0.0.beta16'
elsif active_admin_ver.match?(/[a-zA-Z]/) || active_admin_ver.match?(/^[~<>=]/)
active_admin_ver
else
target = Gem::Version.new(active_admin_ver)
if target >= Gem::Version.new('4.0')
'~> 4.0.0.beta16'
else
active_admin_ver.count('.') < 2 ? "~> #{active_admin_ver}.0" : "~> #{active_admin_ver}"
end
end
gem 'activeadmin', active_admin_requirement
ruby32 = ruby_ver.empty? || Gem::Version.new(ruby_ver) >= Gem::Version.new('3.2')
rails72 = rails_ver.empty? || Gem::Version.new(rails_ver) >= Gem::Version.new('7.2')
sqlite3 = ruby32 && rails72 ? ['sqlite3'] : ['sqlite3', '~> 1.4']
gem(*sqlite3)
gem 'zeitwerk', '~> 2.6.18' unless ruby32
# NOTE: to avoid error: uninitialized constant ActiveSupport::LoggerThreadSafeLevel::Logger
gem 'concurrent-ruby', '1.3.4'
# Misc
gem 'bigdecimal'
gem 'csv'
gem 'mutex_m'
gem 'puma'
# Asset pipeline - use Propshaft for Rails 8, Sprockets for older versions
rails80 = rails_ver.empty? || Gem::Version.new(rails_ver) >= Gem::Version.new('8.0')
if rails80
gem 'importmap-rails' # Required for ActiveAdmin 4
gem 'propshaft'
else
gem 'sassc'
gem 'sprockets-rails'
end
gem 'sassc'
gem 'sprockets-rails'
# Testing
gem 'capybara'
gem 'cuprite'
gem 'rspec_junit_formatter'
gem 'rspec-rails'
gem 'simplecov', require: false
gem 'super_diff'
gem 'rspec-retry'
# Linters
gem 'fasterer'
@@ -88,5 +46,4 @@ gem 'rubocop-rspec'
gem 'rubocop-rspec_rails'
# Tools
gem 'appraisal'
gem 'pry-rails'

Просмотреть файл

@@ -1,47 +1,38 @@
include extra/.env
help:
@echo -e "${COMPOSE_PROJECT_NAME} - Main project commands:\n\
make up # starts the dev services (optional env vars: RUBY / RAILS / ACTIVEADMIN)\n\
make specs # run the tests (after up)\n\
make lint # run the linters (after up)\n\
make server # run the server (after up)\n\
make shell # open a shell (after up)\n\
make down # cleanup (after up)\n\
Example: RUBY=3.2 RAILS=7.1 ACTIVEADMIN=3.2.0 make up"
# System commands
build:
@rm -f Gemfile.lock spec/dummy/db/*.sqlite3
@docker compose -f extra/docker-compose.yml build
db_reset:
@docker compose -f extra/docker-compose.yml run --rm app bin/rails db:create db:migrate db:test:prepare
up: build db_reset
@docker compose -f extra/docker-compose.yml up
shell:
@docker compose -f extra/docker-compose.yml exec app bash
@echo "Main targets: up / down / console / shell"
# Docker commands
down:
@docker compose -f extra/docker-compose.yml down --volumes --rmi local --remove-orphans
docker compose down
# App commands
up:
docker compose up
seed:
@docker compose -f extra/docker-compose.yml exec app bin/rails db:seed
attach:
docker compose attach app
console: seed
@docker compose -f extra/docker-compose.yml exec app bin/rails console
up_attach:
docker compose up -d && docker compose attach app
lint:
@docker compose -f extra/docker-compose.yml exec app bin/rubocop
cleanup:
docker container rm -f activeadmin_quill_editor_app && docker image rm -f activeadmin_quill_editor-app
server: seed
@rm -f spec/dummy/tmp/pids/server.pid
@docker compose -f extra/docker-compose.yml exec app bin/rails server -b 0.0.0.0 -p ${SERVER_PORT}
# Rails specific commands
console:
docker compose exec -e "PAGER=more" app bin/rails console
routes:
docker compose exec app bin/rails routes
specs:
@docker compose -f extra/docker-compose.yml exec app bin/rspec --fail-fast
docker compose exec app bin/rspec --fail-fast
# Other commands
bundle:
docker compose exec app bundle
shell:
docker compose exec -e "PAGER=more" app bash
lint:
docker compose exec app bin/rubocop

Просмотреть файл

@@ -17,7 +17,7 @@ Please :star: if you like it.
## Install
_NOTE_: the gem 2.x provide Quill 2.x, while Quill 1.x is provided with the gem version 1.x
_NOTE_: Ruby 2.7 is supported until version 1.1.0
After installing Active Admin, add to your Gemfile: `gem 'activeadmin_quill_editor'` (and execute *bundle*)
@@ -35,6 +35,8 @@ If you installed Active Admin without Webpacker support (default for now):
//= require activeadmin/quill_editor_input
```
> **UPDATE FROM VERSION <= 2.0**: please add to your _app/assets/stylesheets/active_admin.scss_ the line `@import 'activeadmin/quill_editor/quill.snow';`
If you installed Active Admin with Webpacker support:
- Execute in your project root:
@@ -115,7 +117,50 @@ Some methods are provided for advanced use cases:
Project created by [Mattia Roccoberton](http://blocknot.es), thanks also to the good guys that opened issues and pull requests from time to time.
For development information please check [this document](extra/development.md).
There 3 ways to interact with this project:
1) Using Docker:
```sh
# Run rails server on the dummy app (=> http://localhost:3000 to access to ActiveAdmin):
make up
# Enter in a Rails console (with the dummy app started):
make console
# Enter in a shell (with the dummy app started):
make shell
# Run the linter on the project (with the dummy app started):
make lint
# Run the test suite (with the dummy app started):
make specs
# Remove container and image:
make cleanup
# To try different versions of Ruby/Rails/ActiveAdmin edit docker-compose.yml
# For more commands please check the Makefile
```
2) Using Appraisal:
```sh
export RAILS_ENV=development
# Install dependencies
bin/appraisal
# Run server (or any command)
bin/appraisal rails s
# Or with specific versions
bin/appraisal rails71-activeadmin rails s
```
3) With a local setup:
```sh
# Dev setup (set the required envs)
source extra/dev_setup.sh
# Install dependencies
bundle
# Run server (or any command)
bin/rails s
# To try different versions of Rails/ActiveAdmin edit extra/dev_setup.sh
```
## Do you like it? Star it!

Просмотреть файл

@@ -1,16 +1,5 @@
# frozen_string_literal: true
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end
APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
load 'rails/tasks/engine.rake'
load 'rails/tasks/statistics.rake'
require 'bundler/gem_tasks'
begin

Просмотреть файл

@@ -5,26 +5,27 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'activeadmin/quill_editor/version'
Gem::Specification.new do |spec|
spec.name = 'activeadmin-quill_editor'
spec.name = 'activeadmin_quill_editor'
spec.version = ActiveAdmin::QuillEditor::VERSION
spec.summary = 'Quill Editor for ActiveAdmin'
spec.description = 'An Active Admin plugin to use Quill Rich Text Editor'
spec.license = 'MIT'
spec.authors = ['Mattia Roccoberton']
spec.email = 'mat@blocknot.es'
spec.homepage = 'https://github.com/rs-pro/activeadmin-quill_editor'
spec.homepage = 'https://github.com/blocknotes/activeadmin_quill_editor'
spec.required_ruby_version = '>= 3.0'
spec.metadata['homepage_uri'] = spec.homepage
spec.metadata['changelog_uri'] = 'https://github.com/rs-pro/activeadmin-quill_editor/blob/main/CHANGELOG.md'
spec.metadata['changelog_uri'] = 'https://github.com/blocknotes/activeadmin_quill_editor/blob/main/CHANGELOG.md'
spec.metadata['source_code_uri'] = spec.homepage
spec.metadata['rubygems_mfa_required'] = 'true'
spec.files = Dir['{app,lib,vendor}/**/*', 'LICENSE.txt', 'Rakefile', 'README.md']
spec.files = Dir['{app,lib}/**/*', 'LICENSE.txt', 'Rakefile', 'README.md']
spec.require_paths = ['lib']
spec.add_dependency 'activeadmin', '>= 2.9', '< 5'
spec.add_dependency 'rails', '>= 6.0'
spec.add_runtime_dependency 'activeadmin', '>= 2.9', '< 4' # rubocop:disable Gemspec/AddRuntimeDependency
spec.add_development_dependency 'appraisal', '~> 2.4' # rubocop:disable Gemspec/DevelopmentDependencies
end

Просмотреть файл

@@ -1,362 +0,0 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _blots_image_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var _quill_imageUploader_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
/* harmony import */ var _quill_imageUploader_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_quill_imageUploader_css__WEBPACK_IMPORTED_MODULE_1__);
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var ImageUploader = function () {
function ImageUploader(quill, options) {
_classCallCheck(this, ImageUploader);
this.quill = quill;
this.options = options;
this.range = null;
if (typeof this.options.upload !== "function") {
console.warn("[Missing config] upload function that returns a promise is required");
}
if (this.options.loadingClass) {
_blots_image_js__WEBPACK_IMPORTED_MODULE_0__["default"].className = this.options.loadingClass;
}
var toolbar = this.quill.getModule("toolbar");
toolbar.addHandler("image", this.selectLocalImage.bind(this));
this.handleDrop = this.handleDrop.bind(this);
this.handlePaste = this.handlePaste.bind(this);
this.quill.root.addEventListener("drop", this.handleDrop, false);
this.quill.root.addEventListener("paste", this.handlePaste, false);
}
_createClass(ImageUploader, [{
key: "selectLocalImage",
value: function selectLocalImage() {
var _this = this;
this.range = this.quill.getSelection();
this.fileHolder = document.createElement("input");
this.fileHolder.setAttribute("type", "file");
this.fileHolder.setAttribute("accept", "image/*");
this.fileHolder.setAttribute("style", "visibility:hidden");
this.fileHolder.onchange = this.fileChanged.bind(this);
document.body.appendChild(this.fileHolder);
this.fileHolder.click();
window.requestAnimationFrame(function () {
document.body.removeChild(_this.fileHolder);
});
}
}, {
key: "handleDrop",
value: function handleDrop(evt) {
var _this2 = this;
evt.stopPropagation();
evt.preventDefault();
if (evt.dataTransfer && evt.dataTransfer.files && evt.dataTransfer.files.length) {
if (document.caretRangeFromPoint) {
var selection = document.getSelection();
var range = document.caretRangeFromPoint(evt.clientX, evt.clientY);
if (selection && range) {
selection.setBaseAndExtent(range.startContainer, range.startOffset, range.startContainer, range.startOffset);
}
} else {
var _selection = document.getSelection();
var _range = document.caretPositionFromPoint(evt.clientX, evt.clientY);
if (_selection && _range) {
_selection.setBaseAndExtent(_range.offsetNode, _range.offset, _range.offsetNode, _range.offset);
}
}
this.range = this.quill.getSelection();
var file = evt.dataTransfer.files[0];
setTimeout(function () {
_this2.range = _this2.quill.getSelection();
_this2.readAndUploadFile(file);
}, 0);
}
}
}, {
key: "handlePaste",
value: function handlePaste(evt) {
var _this3 = this;
var clipboard = evt.clipboardData || window.clipboardData;
// IE 11 is .files other browsers are .items
if (clipboard && (clipboard.items || clipboard.files)) {
var items = clipboard.items || clipboard.files;
var IMAGE_MIME_REGEX = /^image\/(jpe?g|gif|png|svg|webp)$/i;
for (var i = 0; i < items.length; i++) {
if (IMAGE_MIME_REGEX.test(items[i].type)) {
(function () {
var file = items[i].getAsFile ? items[i].getAsFile() : items[i];
if (file) {
_this3.range = _this3.quill.getSelection();
evt.preventDefault();
setTimeout(function () {
_this3.range = _this3.quill.getSelection();
_this3.readAndUploadFile(file);
}, 0);
}
})();
}
}
}
}
}, {
key: "readAndUploadFile",
value: function readAndUploadFile(file) {
var _this4 = this;
var isUploadReject = false;
var fileReader = new FileReader();
fileReader.addEventListener("load", function () {
if (!isUploadReject) {
var base64ImageSrc = fileReader.result;
_this4.insertBase64Image(base64ImageSrc);
}
}, false);
if (file) {
fileReader.readAsDataURL(file);
}
this.options.upload(file).then(function (imageUrl) {
_this4.insertToEditor(imageUrl);
}, function (error) {
isUploadReject = true;
_this4.removeBase64Image();
console.warn(error);
});
}
}, {
key: "fileChanged",
value: function fileChanged() {
var file = this.fileHolder.files[0];
this.readAndUploadFile(file);
}
}, {
key: "insertBase64Image",
value: function insertBase64Image(url) {
var range = this.range;
this.quill.insertEmbed(range.index, _blots_image_js__WEBPACK_IMPORTED_MODULE_0__["default"].blotName, "" + url, "user");
}
}, {
key: "insertToEditor",
value: function insertToEditor(url) {
var range = this.range;
// Delete the placeholder image
this.quill.deleteText(range.index, 3, "user");
// Insert the server saved image
this.quill.insertEmbed(range.index, "image", "" + url, "user");
range.index++;
this.quill.setSelection(range, "user");
}
}, {
key: "removeBase64Image",
value: function removeBase64Image() {
var range = this.range;
this.quill.deleteText(range.index, 3, "user");
}
}]);
return ImageUploader;
}();
window.ImageUploader = ImageUploader;
/* harmony default export */ __webpack_exports__["default"] = (ImageUploader);
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var quill__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
/* harmony import */ var quill__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(quill__WEBPACK_IMPORTED_MODULE_0__);
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var InlineBlot = quill__WEBPACK_IMPORTED_MODULE_0___default.a.import('blots/block');
var LoadingImage = function (_InlineBlot) {
_inherits(LoadingImage, _InlineBlot);
function LoadingImage() {
_classCallCheck(this, LoadingImage);
return _possibleConstructorReturn(this, (LoadingImage.__proto__ || Object.getPrototypeOf(LoadingImage)).apply(this, arguments));
}
_createClass(LoadingImage, [{
key: 'deleteAt',
value: function deleteAt(index, length) {
_get(LoadingImage.prototype.__proto__ || Object.getPrototypeOf(LoadingImage.prototype), 'deleteAt', this).call(this, index, length);
this.cache = {};
}
}], [{
key: 'create',
value: function create(src) {
var node = _get(LoadingImage.__proto__ || Object.getPrototypeOf(LoadingImage), 'create', this).call(this, src);
if (src === true) return node;
var image = document.createElement('img');
image.setAttribute('src', src);
node.appendChild(image);
return node;
}
}, {
key: 'value',
value: function value(domNode) {
var _domNode$dataset = domNode.dataset,
src = _domNode$dataset.src,
custom = _domNode$dataset.custom;
return { src: src, custom: custom };
}
}]);
return LoadingImage;
}(InlineBlot);
LoadingImage.blotName = 'imageBlot';
LoadingImage.className = 'quill-image-uploading';
LoadingImage.tagName = 'span';
quill__WEBPACK_IMPORTED_MODULE_0___default.a.register({ 'formats/imageBlot': LoadingImage });
/* harmony default export */ __webpack_exports__["default"] = (LoadingImage);
/***/ }),
/* 2 */
/***/ (function(module, exports) {
module.exports = Quill;
/***/ }),
/* 3 */
/***/ (function(module, exports) {
// removed by extract-text-webpack-plugin
/***/ })
/******/ ]);

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

8
app/assets/javascripts/activeadmin/quill_editor/quill.min.js поставляемый Обычный файл

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@@ -1,11 +1,11 @@
/* globals $ Quill ImageUploader */
/* eslint-disable no-undef */
(function () {
'use strict';
'use strict'
// --- functions ---------------------------------------------------------------
const initQuillEditors = () => {
const defaultTheme = 'snow';
const defaultToolbar = [
function initQuillEditors() {
let default_theme = 'snow'
let default_toolbar = [
['bold', 'italic', 'underline'],
['link', 'blockquote', 'code-block'],
[{ 'script': 'sub' }, { 'script': 'super' }],
@@ -13,65 +13,59 @@
[{ 'color': [] }, { 'background': [] }],
['image'],
['clean'],
];
const editors = document.querySelectorAll('[data-aa-quill-editor]');
const registeredPlugins = {};
]
let editors = document.querySelectorAll('[data-aa-quill-editor]')
let registered_plugins = {}
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');
let content = editors[i].querySelector('[data-aa-quill-content]')
let 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;
let options = editors[i].getAttribute('data-options') ? JSON.parse(editors[i].getAttribute('data-options')) : {}
if (!options.theme) options.theme = default_theme
if (!options.modules) options.modules = {}
if (!options.modules.toolbar) options.modules.toolbar = default_toolbar
// 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;
let plugin_options = editors[i].getAttribute('data-plugins') ? JSON.parse(editors[i].getAttribute('data-plugins')) : {}
if (plugin_options.image_uploader && plugin_options.image_uploader.server_url) {
if (!registered_plugins.image_uploader) {
Quill.register('modules/imageUploader', ImageUploader)
registered_plugins.image_uploader = true
}
const opts = pluginOptions.image_uploader;
options.modules.imageUploader = setupImageUploader(opts.server_url, opts.field_name);
let opts = plugin_options.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';
editors[i]['_quill-editor'] = new Quill(content, options)
editors[i].classList += ' quill-editor--active'
}
}
const formtastic = document.querySelector('form.formtastic');
let 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"]');
let input = editors[i].querySelector('input[type="hidden"]')
if (editors[i]['_quill-editor'].editor.isBlank()) {
input.value = '';
input.value = ''
} else {
input.value = editors[i]['_quill-editor'].root.innerHTML;
input.value = editors[i]['_quill-editor'].root.innerHTML
}
}
};
}
};
}
const setupImageUploader = (server_url, field_name) => {
function setupImageUploader(server_url, field_name) {
return {
upload: (file) => {
upload: file => {
return new Promise((resolve, reject) => {
const formData = new FormData();
const formData = new FormData()
formData.append(field_name || 'file_upload', file)
formData.append(field_name || 'file_upload', file);
fetch(server_url, {
body: formData,
headers: {
@@ -81,13 +75,13 @@
}).then(response => response.json())
.then(result => {
if (!result.url) {
reject('Upload failed');
reject('Upload failed')
}
resolve(result.url);
})
.catch(error => {
reject('Upload failed');
console.error('Error: ', error);
reject('Upload failed')
console.error('Error: ', error)
})
})
}
@@ -96,28 +90,27 @@
// --- public functions --------------------------------------------------------
window.getQuillEditors = function() {
const editors = document.querySelectorAll('[data-aa-quill-editor]');
const list = [];
const editors = document.querySelectorAll('[data-aa-quill-editor]')
let list = []
editors.forEach(function(editor) { list.push(editor['_quill-editor']) });
return list;
editors.forEach(function(editor) { list.push(editor['_quill-editor']) })
return list
}
window.getQuillEditorByIndex = function(index) {
const editors = document.querySelectorAll('[data-aa-quill-editor]');
const editors = document.querySelectorAll('[data-aa-quill-editor]')
return (index >= 0 && index < editors.length) ? editors[index]['_quill-editor'] : null;
return (index >= 0 && index < editors.length) ? editors[index]['_quill-editor'] : null
}
window.getQuillEditorByElementId = function(id) {
const editor = document.querySelector(`[data-aa-quill-editor]#${id}`);
const editor = document.querySelector(`[data-aa-quill-editor]#${id}`)
return editor ? editor['_quill-editor'] : null;
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);
})();
$(document).ready(initQuillEditors)
$(document).on('has_many_add:after', '.has_many_container', initQuillEditors)
$(document).on('turbolinks:load', initQuillEditors)
})()

Просмотреть файл

@@ -1,15 +1,15 @@
.quill-image-uploading {
.image-uploading {
position: relative;
display: inline-block;
}
.quill-image-uploading img {
.image-uploading img {
max-width: 98% !important;
filter: blur(5px);
opacity: 0.3;
}
.quill-image-uploading::before {
.image-uploading::before {
content: "";
box-sizing: border-box;
position: absolute;
@@ -21,7 +21,7 @@
margin-left: -15px;
border-radius: 50%;
border: 3px solid #ccc;
border-top-color: #1e40af;
border-top-color: #1e986c;
z-index: 1;
animation: spinner 0.6s linear infinite;
}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

29
bin/appraisal Исполняемый файл
Просмотреть файл

@@ -0,0 +1,29 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
#
# This file was generated by Bundler.
#
# The application 'appraisal' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)
bundle_binstub = File.expand_path("../bundle", __FILE__)
if File.file?(bundle_binstub)
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
load(bundle_binstub)
else
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
end
end
require "rubygems"
require "bundler/setup"
load Gem.bin_path("appraisal", "appraisal")

Просмотреть файл

@@ -2,7 +2,7 @@
# This command will automatically be run when you run "rails" with Rails gems
# installed from the root of your application.
ENV['RAILS_ENV'] ||= 'development'
ENV['RAILS_ENV'] ||= 'test'
ENGINE_ROOT = File.expand_path('..', __dir__)
ENGINE_PATH = File.expand_path('../lib/activeadmin/quill_editor/engine', __dir__)

25
docker-compose.yml Обычный файл
Просмотреть файл

@@ -0,0 +1,25 @@
services:
app:
container_name: 'activeadmin_quill_editor_app'
build:
context: .
dockerfile: ./extra/Dockerfile
# dockerfile: ./extra/Dockerfile_alpine
args:
# Debian-based Ruby image:
RUBY_IMAGE: ruby:3.4-slim
UID: ${UID}
environment:
ACTIVEADMIN_VERSION: ~> 3.3
RAILS_VERSION: ~> 8.0
user: "${UID}:${GID}"
ports:
- '3000:3000'
working_dir: '/app'
volumes:
- '.:/app'
stdin_open: true
tty: true
entrypoint:
- /bin/sh
- ./extra/entrypoint.sh

Просмотреть файл

@@ -1,932 +0,0 @@
# ActiveAdmin 4 Migration Guide for Gem Maintainers
## Overview
This document provides a comprehensive guide for gem maintainers on how to update their gems to support ActiveAdmin 4, based on the changes made to the `activeadmin-searchable_select` gem. The migration involved addressing significant changes in asset handling, JavaScript module systems, dependency management, and CSS selectors.
## Key Migration Steps
### 1. Update Dependency Constraints
#### Ruby Version Requirements
- **Minimum Ruby version**: 3.2 (Ruby 3.0 and 3.1 are dropped in ActiveAdmin 4)
- Update your gemspec: `spec.required_ruby_version = '>= 3.2'`
#### Rails Version Requirements
- **Minimum Rails version**: 7.0 (Rails 6.1 support dropped)
- ActiveAdmin 4 supports Rails 7.x and 8.x
#### ActiveAdmin Version
```ruby
# In gemspec
spec.add_runtime_dependency 'activeadmin', ['>= 1.x', '< 5']
```
### 2. Asset Pipeline Migration
ActiveAdmin 4 moved away from the traditional Rails asset pipeline to modern JavaScript bundlers.
#### Key Changes:
- ActiveAdmin 4 assumes `cssbundling-rails` and `importmap-rails` are installed
- No longer uses `register_stylesheet` or `register_javascript` methods
- Requires explicit JavaScript module initialization
#### CSS bundling pattern (Rails 7 cssbundling + Tailwind)
- Build CSS to `app/assets/builds/active_admin.css` and expose it via `app/assets/config/manifest.js`:
- `//= link_tree ../builds`
- `//= link active_admin.css`
- `//= link active_admin.js`
- `//= link trumbowyg/icons.svg` (when using Trumbowyg)
- Keep a single Tailwind config at the Rails app root (avoid duplicates). Using ESM works well:
- `tailwind.config.mjs` with `import activeAdminPlugin from '@activeadmin/activeadmin/plugin'`
- Source file `app/assets/stylesheets/active_admin_source.css` contains Tailwind directives, gem overrides and imports.
- If Tailwind CLI does not inline vendor `@import` from `node_modules`, concatenate vendor CSS before building. Example build script:
```json
// spec/internal/package.json
{
"scripts": {
"build:css": "node ./build_css.js"
}
}
```
```js
// spec/internal/build_css.js
const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');
const root = __dirname;
const inputPath = path.join(root, 'app/assets/stylesheets/active_admin_source.css');
const vendorCssPath = path.join(root, 'node_modules/trumbowyg/dist/ui/trumbowyg.css');
const tmpPath = path.join(root, 'app/assets/stylesheets/__aa_tmp.css');
const outPath = path.join(root, 'app/assets/builds/active_admin.css');
const src = fs.readFileSync(inputPath, 'utf8').split(/\r?\n/);
const vendorCss = fs.readFileSync(vendorCssPath, 'utf8');
const tailwind = ['@tailwind base;','@tailwind components;','@tailwind utilities;'].join('\n');
const body = src.slice(3).filter(l => !l.includes('trumbowyg.css')).join('\n');
fs.writeFileSync(tmpPath, `${tailwind}\n\n${vendorCss}\n\n${body}`);
spawnSync('npx', ['tailwindcss','-c', path.join(root,'tailwind.config.mjs'),'-i', tmpPath,'-o', outPath], { stdio: 'inherit', cwd: root });
fs.unlinkSync(tmpPath);
```
This ensures vendor CSS (e.g., Trumbowyg) ships inside the built `active_admin.css` while keeping Tailwind at the top of the cascade so overrides behave as expected.
#### JavaScript Module Support
Create multiple module formats to support different bundlers:
1. **ESM Module** (`your_gem.esm.js`):
```javascript
import $ from 'jquery';
import select2 from 'select2'; // Or your jQuery plugin
// Critical: Initialize jQuery plugins on the jQuery object for production builds
// This ensures the plugin methods are available on jQuery selections
select2($);
// Ensure jQuery is globally available for other scripts
window.$ = window.jQuery = $;
// Your initialization code wrapped in a DOM ready handler
$(() => {
// Initialize your plugin on specific selectors
$('.your-selector').yourPlugin({
// plugin options
});
// Listen for Turbo/Turbolinks events for dynamic content
$(document).on('turbo:load turbolinks:load', () => {
$('.your-selector').yourPlugin();
});
// For ActiveAdmin's dynamic content (filters, forms)
$(document).on('has_many_add:after', '.has_many_container', () => {
$('.your-selector').yourPlugin();
});
});
// Export for use as a module
export default function initializeYourGem() {
// Initialization logic
}
```
2. **Traditional Module** (`your_gem.js` for backward compatibility):
```javascript
//= require jquery
//= require select2
(function($) {
'use strict';
$(document).ready(function() {
$('.your-selector').yourPlugin();
});
// Turbolinks/Turbo support
$(document).on('turbo:load turbolinks:load', function() {
$('.your-selector').yourPlugin();
});
})(jQuery);
```
3. **CDN-compatible version** (for importmap users):
```javascript
// Assumes jQuery and plugins are loaded via CDN
(() => {
'use strict';
const $ = window.jQuery || window.$;
if (!$) {
console.error('jQuery is required for YourGem');
return;
}
// Wait for DOM ready
$(() => {
$('.your-selector').yourPlugin();
});
})();
```
### 3. Installation Generator
Create a generator to help users set up your gem with different bundlers:
```ruby
module YourGem
module Generators
class InstallGenerator < Rails::Generators::Base
class_option :bundler,
type: :string,
default: 'esbuild',
enum: %w[esbuild importmap webpack]
def setup_javascript
case options[:bundler]
when 'esbuild'
setup_esbuild
when 'importmap'
setup_importmap
when 'webpack'
setup_webpack
end
end
private
def setup_esbuild
# Add imports to app/javascript/active_admin.js
append_to_file 'app/javascript/active_admin.js' do
<<~JS
import $ from 'jquery';
import yourPlugin from 'your-plugin';
// Initialize plugin on jQuery
yourPlugin($);
window.$ = window.jQuery = $;
import '@your-scope/your-gem';
JS
end
end
def setup_importmap
# Add pins to config/importmap.rb
append_to_file 'config/importmap.rb' do
<<~RUBY
pin "jquery", to: "https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"
pin "your-plugin", to: "https://cdn.jsdelivr.net/npm/your-plugin/dist/plugin.min.js"
pin "your-gem", to: "your-gem.js"
RUBY
end
end
end
end
end
```
### 4. NPM Package Publishing
If your gem includes JavaScript, consider publishing an NPM package:
#### Package.json Configuration
```json
{
"name": "@activeadmin/your-gem",
"version": "1.0.0",
"description": "Your gem description for ActiveAdmin",
"main": "src/index.js",
"module": "src/index.js",
"exports": {
".": {
"import": "./src/index.js",
"require": "./src/index.js",
"default": "./src/index.js"
},
"./css": "./src/styles.scss"
},
"peerDependencies": {
"jquery": ">= 3.0, < 5",
"select2": "^4.0.13" // Add your dependencies here
},
"files": [
"src/**/*",
"app/assets/**/*",
"vendor/assets/**/*"
],
"scripts": {
"prepare_sources": "mkdir -p src && cp -r app/assets/javascripts/active_admin/* src/ && cp -r app/assets/stylesheets/active_admin/* src/",
"prepublishOnly": "npm run prepare_sources"
},
"repository": {
"type": "git",
"url": "https://github.com/your-org/your-gem.git"
},
"keywords": ["activeadmin", "rails", "your-feature"],
"author": "Your Name",
"license": "MIT"
}
```
#### Preparing JavaScript Assets for NPM
Create a script to copy your assets to the NPM package structure:
```bash
#!/bin/bash
# scripts/prepare_npm_package.sh
# Create src directory for NPM
mkdir -p src
# Copy JavaScript files
cp -r app/assets/javascripts/active_admin/* src/
# Copy SCSS files if needed
cp -r app/assets/stylesheets/active_admin/* src/
# Ensure ESM module is included
cp app/assets/javascripts/active_admin/your_gem.esm.js src/index.js
```
### 5. CSS Selector Updates
ActiveAdmin 4 introduced several CSS class changes:
| ActiveAdmin 3.x | ActiveAdmin 4.x |
|----------------|-----------------|
| `.filter_form` | `.filters-form` |
| `.tabs` component | Removed - use divs with Tailwind |
| `.columns` component | Replaced with Tailwind grid |
Update your JavaScript and CSS accordingly:
```javascript
// Old
$('.filter_form select').select2();
// New
$('.filters-form select').select2();
```
### 6. Testing Updates with Combustion
#### Complete Combustion Workflow for ActiveAdmin 4 Gems
**CRITICAL**: This workflow is specifically for testing ActiveAdmin extension gems with Combustion.
##### Step 1: Add Dependencies to Gemfile
```ruby
# Gemfile (for development/testing)
gem 'combustion'
gem 'importmap-rails', '~> 2.0' # Required for ActiveAdmin 4
```
##### Step 2: Run Combustion Generator (MANDATORY!)
```bash
# NEVER manually create spec/internal structure!
bundle exec combust
```
This creates:
- `spec/internal/` - minimal Rails app structure
- `config.ru` - in gem root for `bundle exec rackup`
- Basic Rails directories and config files
##### Step 3: Set Up Test App Structure
After generator, create these files:
```bash
# Create necessary directories
mkdir -p spec/internal/app/models
mkdir -p spec/internal/app/admin
mkdir -p spec/internal/app/assets/stylesheets
mkdir -p spec/internal/app/javascript
mkdir -p spec/internal/config/initializers
```
##### Basic Combustion Configuration
```ruby
# spec/rails_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require 'combustion'
# Initialize Combustion with only needed components
Combustion.path = 'spec/internal'
Combustion.initialize!(:active_record, :action_controller, :action_view) do
config.load_defaults Rails::VERSION::STRING.to_f if Rails::VERSION::MAJOR >= 7
end
require 'rspec/rails'
require 'capybara/rails'
```
##### Step 4: Configure config.ru (CRITICAL Loading Order!)
```ruby
# config.ru - MUST control loading order for ActiveAdmin!
require "rubygems"
require "bundler"
# DON'T use Bundler.require - it loads gems too early!
Bundler.setup(:default, :development)
# Load Rails and combustion first
require 'combustion'
# Initialize Combustion with Rails components
Combustion.initialize! :active_record, :action_controller, :action_view do
config.load_defaults Rails::VERSION::STRING.to_f if Rails::VERSION::MAJOR >= 7
end
# NOW we can load ActiveAdmin and its dependencies after Rails is initialized
require 'importmap-rails'
require 'active_admin'
require 'your_activeadmin_gem'
run Combustion::Application
```
##### Step 5: Configure ActiveAdmin Assets
```ruby
# spec/internal/app/assets/stylesheets/active_admin.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
```ruby
# spec/internal/config/importmap.rb
pin "@activeadmin/activeadmin", to: "active_admin.js", preload: true
```
```javascript
// spec/internal/app/javascript/active_admin.js
// Placeholder for ActiveAdmin JS
console.log("ActiveAdmin loaded");
```
##### Step 6: Set Up Test Models and Admin Resources
```ruby
# spec/internal/db/schema.rb
ActiveRecord::Schema.define do
create_table :active_admin_comments, force: true do |t|
t.string :namespace
t.text :body
t.references :resource, polymorphic: true
t.references :author, polymorphic: true
t.timestamps
end
create_table :posts, force: true do |t|
t.string :title
t.text :body
t.text :description
t.timestamps
end
end
```
```ruby
# spec/internal/config/routes.rb
Rails.application.routes.draw do
ActiveAdmin.routes(self)
root to: 'admin/dashboard#index'
end
```
```ruby
# spec/internal/config/initializers/active_admin.rb
ActiveAdmin.setup do |config|
config.site_title = "Test App"
config.authentication_method = false
config.current_user_method = false
config.batch_actions = true
end
```
##### Step 7: Configure rails_helper.rb
```ruby
# spec/rails_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require 'combustion'
Combustion.path = 'spec/internal'
Combustion.initialize!(:active_record, :action_controller, :action_view) do
config.load_defaults Rails::VERSION::STRING.to_f if Rails::VERSION::MAJOR >= 7
end
require 'rspec/rails'
require 'capybara/rails'
```
##### Step 8: Running the Test App
```bash
# Start the test app server
bundle exec rackup
# Visit http://localhost:9292/admin
```
#### Critical Testing Pitfall: Model Registration Conflicts
**Problem**: Dynamic ActiveAdmin registrations in tests conflict with static admin files.
**Solution**: Choose ONE approach per model:
1. **Static Registration** (for consistent configs):
```ruby
# spec/internal/app/admin/users.rb
ActiveAdmin.register User do
permit_params :name, :email
# Fixed configuration
end
```
2. **Dynamic Registration** (for varying configs):
```ruby
# spec/support/active_admin_helpers.rb
module ActiveAdminHelpers
module_function
def setup
ActiveAdmin.application = nil
yield # Dynamic registration block
reload_routes!
end
def reload_routes!
Rails.application.reload_routes!
end
end
# In test - NO static admin file for Post model
ActiveAdminHelpers.setup do
ActiveAdmin.register(Post) do
# Test-specific configuration
end
end
```
**Important**: Never mix static and dynamic registration for the same model!
#### Capybara Configuration with Playwright
```ruby
# spec/support/capybara.rb
require 'capybara-playwright-driver'
Capybara.register_driver :playwright do |app|
Capybara::Playwright::Driver.new(
app,
browser_type: :chromium,
headless: true,
viewport: { width: 1920, height: 1080 }
)
end
Capybara.default_driver = :rack_test
Capybara.javascript_driver = :playwright
# Important: Set server for JS tests
Capybara.server = :puma, { Silent: true }
```
#### Waiting for JavaScript/AJAX in Tests
```ruby
# spec/support/wait_helpers.rb
module WaitHelpers
def wait_for_ajax
Timeout.timeout(Capybara.default_max_wait_time) do
sleep 0.1
loop until finished_all_ajax_requests?
end
end
def finished_all_ajax_requests?
page.evaluate_script('jQuery.active').zero?
end
# For Select2 or similar plugins
def wait_for_select2
expect(page).to have_css('.select2-container', wait: 5)
end
end
RSpec.configure do |config|
config.include WaitHelpers, type: :feature
end
```
### 7. Production Build Issues
Common production issues and solutions:
#### Issue: JavaScript plugin not initialized
**Solution**: Explicitly initialize jQuery plugins
```javascript
import select2 from 'select2';
import $ from 'jquery';
// This is critical for production builds
select2($);
```
#### Issue: jQuery not globally available
**Solution**: Ensure global assignment
```javascript
window.$ = window.jQuery = $;
```
#### Issue: Assets not loading in production
**Solution**: Use CDN fallbacks or vendor assets
```ruby
# In your gem's engine.rb
class Engine < ::Rails::Engine
initializer 'your_gem.assets' do |app|
if Rails.env.production?
# Add fallback assets
end
end
end
```
### 8. CI/CD Updates
Update your GitHub Actions workflow:
```yaml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.2', '3.3']
rails: ['7.0', '7.1', '7.2', '8.0']
activeadmin: ['4.0.0.beta16']
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install npm dependencies
run: npm install
- name: Install Playwright browsers
run: npx playwright install chromium
- name: Run tests
run: bundle exec rspec
```
### 9. Appraisals Configuration
Use Appraisal gem to test against multiple versions:
```ruby
# Appraisals file
appraise 'rails-7.x-active-admin-4.x' do
gem 'rails', '~> 7.0'
gem 'activeadmin', '~> 4.0.0.beta16'
gem 'propshaft' # Required - Sprockets not supported
end
appraise 'rails-8.x-active-admin-4.x' do
gem 'rails', '~> 8.0'
gem 'activeadmin', '~> 4.0.0.beta16'
# Rails 8 includes Propshaft by default
end
```
### 10. Common Pitfalls and Solutions
#### Pitfall 1: Select2 or similar jQuery plugins not working
**Root Cause**: Plugin not attached to jQuery object in production
**Solution**: Explicitly call `plugin($)` after importing
```javascript
import select2 from 'select2';
import $ from 'jquery';
select2($); // Critical - attaches plugin to jQuery
```
#### Pitfall 2: CSS classes not found
**Root Cause**: ActiveAdmin 4 changed many CSS selectors
**Solution**: Search and replace old selectors with new ones
- `.filter_form``.filters-form`
- `.select2-container` needs explicit initialization in tests
#### Pitfall 3: Tests passing locally but failing in CI
**Root Cause**: Missing JavaScript dependencies or browser drivers
**Solution**:
```yaml
# .github/workflows/ci.yml
- name: Install Playwright browsers
run: npx playwright install chromium
```
#### Pitfall 4: Assets not compiling in production
**Root Cause**: Missing bundler configuration
**Solution**: Provide clear setup instructions for each bundler type in your README
#### Pitfall 5: Model registration conflicts in tests
**Root Cause**: Static admin files override dynamic test registrations
**Solution**:
- Delete static admin files for models that need dynamic config
- Keep static files only for models with consistent config
- Never mix both approaches for the same model
#### Pitfall 6: Input HTML options not passing through
**Root Cause**: Options can be lost during form DSL processing
**Solution**: Test with clean models not affected by other registrations
```ruby
# Test with a model that has no static admin file
ActiveAdmin.register(TestModel) do
form do |f|
f.input :field, as: :searchable_select,
input_html: { class: 'custom-class' }
end
end
```
#### Pitfall 7: Flaky JavaScript tests
**Root Cause**: Not waiting for AJAX/DOM updates
**Solution**: Add proper wait helpers
```ruby
def wait_for_select2
expect(page).to have_css('.select2-container', wait: 5)
end
```
#### Pitfall 8: Rails 8 compatibility issues
**Root Cause**: Formtastic 5.0 changes, Ransack updates
**Solution**:
- Test against multiple Rails versions using Appraisal
- Ensure Ransack methods are defined in models
```ruby
def self.ransackable_attributes(_auth_object = nil)
%w[name title]
end
```
#### Pitfall 9: Combustion and ActiveAdmin Loading Order Issues
**Root Cause**: ActiveAdmin requires Rails components at load time, conflicts with Combustion's initialization
**Critical Issue**: ActiveAdmin's `Bundler.require` loads before Rails is initialized by Combustion
**Symptoms**:
- `uninitialized constant Formtastic::ActionView`
- `uninitialized constant ActiveSupport::Autoload`
- `uninitialized constant #<Class:ActiveAdmin>::Importmap`
- Rackup fails with various Rails component loading errors
**Solution**:
- Use `Bundler.setup` instead of `Bundler.require` in config.ru
- Load ActiveAdmin AFTER Combustion initializes Rails
- Include importmap-rails for ActiveAdmin 4
- Don't require ActiveAdmin components in gem's main file
```ruby
# Bad: In lib/your_gem.rb
require 'active_admin' # This loads too early!
require 'formtastic/inputs/your_input'
# Good: In engine.rb
initializer 'your_gem.setup', after: :load_config_initializers do
require 'active_admin' if defined?(Rails.application)
ActiveSupport.on_load(:active_admin) do
require 'formtastic/inputs/your_input'
end
end
```
#### Pitfall 10: ActiveAdmin 4 Asset Pipeline Requirements (CRITICAL FOR COMBUSTION GEMS)
**Root Cause**: ActiveAdmin 4 uses Tailwind CSS v3 with custom plugin, requires compilation
**Critical Issue**: CSS must be compiled through Tailwind with ActiveAdmin plugin
**Symptoms**:
- Unstyled admin pages (no proper layout, just basic HTML)
- CSS file exists but has 0 bytes or wrong content
- `The asset "active_admin.css" is not present in the asset pipeline`
**Complete Solution for Combustion-based Gems**:
1. **Add Dependencies** (Gemfile):
```ruby
gem 'importmap-rails', '~> 2.0'
gem 'tailwindcss-rails' # For bundled tailwindcss executable
```
2. **Install NPM packages** (in spec/internal):
```bash
cd spec/internal
npm init -y
npm install --save-dev tailwindcss@^3 # Use v3, not v4!
npm install --save-dev @activeadmin/activeadmin # For plugin (optional)
```
3. **Copy ActiveAdmin Plugin** (from Ruby gem):
```bash
cp $(bundle show activeadmin)/plugin.js spec/internal/activeadmin-plugin.js
```
4. **Create Tailwind Config** (spec/internal/tailwind.config.mjs):
```javascript
import activeAdminPlugin from './activeadmin-plugin.js';
import { execSync } from 'child_process';
const activeAdminPath = execSync('bundle show activeadmin', { encoding: 'utf-8' }).trim();
export default {
content: [
`${activeAdminPath}/app/views/**/*.{arb,erb,html,rb}`,
'./app/admin/**/*.{arb,erb,html,rb}',
'./app/views/**/*.{arb,erb,html}',
'./app/javascript/**/*.js'
],
darkMode: 'selector',
plugins: [activeAdminPlugin]
}
```
5. **Create Source CSS** (spec/internal/app/assets/stylesheets/active_admin_source.css):
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
6. **Build CSS**:
```bash
cd spec/internal
npx tailwindcss -c tailwind.config.mjs \
-i app/assets/stylesheets/active_admin_source.css \
-o app/assets/stylesheets/active_admin_compiled.css \
--minify
```
7. **Configure Sprockets** (spec/internal/app/assets/stylesheets/active_admin.css):
```css
/*
* This imports the compiled Tailwind CSS with ActiveAdmin styles
*= require ./active_admin_compiled
*/
```
8. **Update Manifest** (spec/internal/app/assets/config/manifest.js):
```javascript
//= link_tree ../builds
//= link active_admin.css
```
9. **Create Build Task** (lib/tasks/active_admin.rake):
```ruby
namespace :active_admin do
desc 'Build Active Admin Tailwind stylesheets'
task :build do
require 'fileutils'
input = File.expand_path('../../spec/internal/app/assets/stylesheets/active_admin_source.css', __dir__)
output = File.expand_path('../../spec/internal/app/assets/stylesheets/active_admin_compiled.css', __dir__)
config = File.expand_path('../../spec/internal/tailwind.config.mjs', __dir__)
FileUtils.mkdir_p(File.dirname(output))
command = ['npx', 'tailwindcss', '-c', config, '-i', input, '-o', output, '--minify']
puts "Building Tailwind CSS: #{command.join(' ')}"
system(*command, exception: true)
puts "Tailwind CSS build complete: #{output}"
end
end
```
#### Pitfall 11: Formtastic Custom Inputs Not Loading in Combustion
**Root Cause**: Loading order issues with ActiveAdmin, Formtastic, and custom inputs
**Symptoms**:
- `Formtastic::UnknownInputError: Unable to find input class YourInput`
- Input works in production but not in Combustion test environment
**Solutions**:
1. **Immediate Fix in config.ru** (for Combustion):
```ruby
# config.ru
require 'combustion'
Combustion.initialize! :active_record, :action_controller, :action_view
require 'importmap-rails'
require 'active_admin'
require 'your_gem'
# Critical: Explicitly require custom inputs after everything else
require 'formtastic/inputs/your_input'
run Combustion::Application
```
2. **Engine Initialization Fix**:
```ruby
# lib/your_gem/engine.rb
initializer 'your_gem.setup', after: :load_config_initializers do
require 'active_admin' if defined?(Rails.application)
# Load immediately AND hook into ActiveAdmin
require 'formtastic/inputs/your_input'
ActiveSupport.on_load(:active_admin) do
require 'formtastic/inputs/your_input'
end
end
```
3. **Workaround Using Standard Inputs**:
```ruby
# If custom input isn't loading, use standard input with same attributes
f.input :field, as: :text, input_html: {
class: 'your-input-class',
'data-your-attribute': true
}
```
**Note**: After making these changes, restart the server for them to take effect.
## Migration Checklist
- [ ] Update Ruby version requirement to >= 3.2
- [ ] Update Rails version requirement to >= 7.0
- [ ] Update ActiveAdmin dependency to support 4.x
- [ ] Create ESM JavaScript modules
- [ ] Add installation generator for different bundlers
- [ ] Publish NPM package (if applicable)
- [ ] Update CSS selectors (`.filter_form``.filters-form`)
- [ ] Fix jQuery plugin initialization for production
- [ ] Update test suite for new asset handling
- [ ] Configure CI for multiple version testing
- [ ] Update documentation with setup instructions
- [ ] Test with esbuild, webpack, and importmap
- [ ] Add CDN fallbacks for JavaScript dependencies
- [ ] Handle both Sprockets and Propshaft
## Example Implementation
See the full implementation in the `activeadmin-searchable_select` gem:
- [Installation Generator](../lib/generators/active_admin/searchable_select/install/install_generator.rb)
- [ESM Module](../app/assets/javascripts/active_admin/searchable_select.esm.js)
- [Package.json](../package.json)
- [CI Configuration](../.github/workflows/ci.yml)
## Resources
- [ActiveAdmin 4.0 Breaking Changes](./activeadmin-4-changes.md)
- [ActiveAdmin 4.0 Release Notes](https://github.com/activeadmin/activeadmin/releases)
- [Rails 7+ Asset Pipeline Guide](https://guides.rubyonrails.org/asset_pipeline.html)
- [esbuild Rails Documentation](https://github.com/rails/jsbundling-rails)
- [Importmap Rails Documentation](https://github.com/rails/importmap-rails)
## Conclusion
Migrating a gem to support ActiveAdmin 4 requires careful attention to:
1. Modern JavaScript module systems
2. Flexible asset pipeline support
3. Updated CSS selectors and components
4. Proper jQuery plugin initialization
5. Comprehensive testing across different setups
The key to success is providing multiple paths for users with different asset pipeline configurations while maintaining backward compatibility where possible.

Просмотреть файл

@@ -1,417 +0,0 @@
# ActiveAdmin 4 Gem Update Guide
This guide documents the process of updating a gem to support ActiveAdmin 4 with Propshaft, Tailwind CSS, and modern Rails 8 asset pipeline.
## Overview
ActiveAdmin 4 represents a significant architectural shift from previous versions:
- **CSS**: From Sprockets/SCSS to Tailwind CSS with custom build process
- **JavaScript**: From jQuery to vanilla JavaScript with ES modules
- **Asset Pipeline**: From Sprockets to Propshaft (Rails 8 default)
- **Styling**: From pre-built CSS to user-built Tailwind CSS
## Key Changes Required
### 1. Gem Structure Changes
#### Remove CSS Assets
ActiveAdmin 4 gems should NOT ship CSS files. Users build their own CSS with Tailwind.
```
# Remove these directories/files:
vendor/assets/stylesheets/
app/assets/stylesheets/*.scss
```
#### JavaScript Assets
Keep only initialization JavaScript in vendor/assets:
```
vendor/assets/javascripts/your_gem_name.js # Vanilla JS, no jQuery
```
### 2. Engine Configuration
Update `lib/your_gem/engine.rb`:
```ruby
module YourGem
class Engine < ::Rails::Engine
# Propshaft automatically includes vendor/assets and app/assets paths
initializer 'your_gem.assets' do |app|
# For Propshaft (Rails 8 default)
if defined?(Propshaft)
app.config.assets.precompile += %w[
your_gem_name.js
]
# For Sprockets (legacy support)
elsif app.config.respond_to?(:assets)
app.config.assets.precompile += %w[
your_gem_name.js
]
end
end
end
end
```
### 3. JavaScript Migration
#### Remove jQuery Dependencies
Convert all jQuery code to vanilla JavaScript:
```javascript
// Old (jQuery)
$(document).ready(function() {
$('.quill-editor').each(function() {
// initialization
});
});
// New (Vanilla JS)
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.quill-editor').forEach(function(element) {
// initialization
});
});
```
#### Event Handling
Use modern event delegation:
```javascript
// Support both Turbo and non-Turbo apps
['DOMContentLoaded', 'turbo:load', 'turbolinks:load'].forEach(function(eventName) {
document.addEventListener(eventName, initializeEditors);
});
```
### 4. Test/Dummy App Setup
#### Package.json
Create a proper `package.json` for the test app:
```json
{
"name": "your-gem-test-app",
"private": true,
"scripts": {
"build:js": "node esbuild.config.js",
"build:css": "bundle exec rake active_admin:build",
"build": "npm run build:js && npm run build:css"
},
"dependencies": {
"@activeadmin/activeadmin": "^4.0.0-beta16",
"@rails/ujs": "^7.1.3",
"your-required-npm-package": "^x.x.x"
},
"devDependencies": {
"esbuild": "^0.19.0",
"tailwindcss": "^3.4.17"
}
}
```
#### Tailwind Configuration
Create `tailwind.config.js`:
```javascript
const execSync = require('child_process').execSync;
const activeAdminPath = execSync('bundle show activeadmin', { encoding: 'utf-8' }).trim();
module.exports = {
content: [
`${activeAdminPath}/vendor/javascript/flowbite.js`,
`${activeAdminPath}/plugin.js`,
`${activeAdminPath}/app/views/**/*.{arb,erb,html,rb}`,
'./app/admin/**/*.{arb,erb,html,rb}',
'./app/views/active_admin/**/*.{arb,erb,html,rb}',
'./app/views/admin/**/*.{arb,erb,html,rb}',
'./app/javascript/**/*.js'
],
darkMode: "class",
plugins: [
require('@activeadmin/activeadmin/plugin')
]
};
```
#### CSS Source File Structure
Place source CSS OUTSIDE of Rails asset paths to avoid Propshaft conflicts:
```
spec/dummy/
app/
css/ # NOT in assets/
active_admin_source.css # Source file for Tailwind
assets/
builds/
active_admin.css # Built output
config/
manifest.js # Propshaft manifest
```
#### Active Admin CSS Source
Create `app/css/active_admin_source.css` (or `app/assets/stylesheets/active_admin.css` per the gist):
```css
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
/* Import vendor styles if needed */
@import "../../../node_modules/your-package/dist/styles.css";
/* Custom component styles */
@layer components {
.your-component {
@apply border border-gray-300 rounded-md;
}
}
```
#### Build Task
Create `lib/tasks/active_admin.rake`:
```ruby
namespace :active_admin do
desc "Build Active Admin Tailwind stylesheets"
task build: :environment do
command = [
"npx", "tailwindcss",
"-i", Rails.root.join("app/assets/stylesheets/active_admin.css").to_s,
"-o", Rails.root.join("app/assets/builds/active_admin.css").to_s,
"-c", Rails.root.join("tailwind.config.js").to_s,
"-m"
]
system(*command, exception: true)
end
desc "Watch Active Admin Tailwind stylesheets"
task watch: :environment do
command = [
"npx", "tailwindcss",
"--watch",
"-i", Rails.root.join("app/assets/stylesheets/active_admin.css").to_s,
"-o", Rails.root.join("app/assets/builds/active_admin.css").to_s,
"-c", Rails.root.join("tailwind.config.js").to_s,
"-m"
]
system(*command)
end
end
Rake::Task["assets:precompile"].enhance(["active_admin:build"])
```
#### ESBuild Configuration
Create `esbuild.config.js`:
```javascript
const esbuild = require('esbuild');
const railsEnv = process.env.RAILS_ENV || 'development';
const config = {
entryPoints: ['app/javascript/active_admin.js'],
bundle: true,
sourcemap: railsEnv !== 'production',
format: 'esm',
outdir: 'app/assets/builds',
publicPath: '/assets',
loader: {
'.js': 'js',
},
minify: railsEnv === 'production',
plugins: [],
};
if (process.argv.includes('--watch')) {
esbuild.context(config).then((ctx) => {
ctx.watch();
console.log('Watching for changes...');
});
} else {
esbuild.build(config).then(() => {
console.log('Build completed');
}).catch(() => process.exit(1));
}
```
### 5. ActiveAdmin Initializer
Update `config/initializers/active_admin.rb`:
```ruby
ActiveAdmin.setup do |config|
# Register CSS (required for AA4 + Propshaft)
config.register_stylesheet 'active_admin.css'
# Register JavaScript files
config.register_javascript 'active_admin.js'
config.register_javascript 'your_gem_name.js'
# ... other configuration
end
```
### 6. Propshaft Manifest
Update `app/assets/config/manifest.js`:
```javascript
//= link_tree ../images
//= link_tree ../builds
//= link active_admin.css
//= link active_admin.js
//= link your_gem_name.js
```
### 7. Common Pitfalls & Solutions
#### Issue: CSS not loading / Only Tailwind directives visible
**Cause**: Propshaft serving source file instead of built file
**Solution**:
- Ensure source CSS is outside `app/assets/` or named differently
- Check that build process outputs to `app/assets/builds/`
- Verify `config.register_stylesheet 'active_admin.css'` in initializer
#### Issue: Missing ActiveAdmin layout styles
**Cause**: ActiveAdmin plugin not loaded or content paths missing
**Solution**:
- Ensure `@activeadmin/activeadmin` npm package is installed
- Add ActiveAdmin gem paths to Tailwind content configuration
- Use `require('@activeadmin/activeadmin/plugin')` in Tailwind config
#### Issue: JavaScript not initializing
**Cause**: Turbo/Turbolinks events not handled
**Solution**: Listen for multiple initialization events:
```javascript
['DOMContentLoaded', 'turbo:load', 'turbolinks:load'].forEach(function(eventName) {
document.addEventListener(eventName, initializeComponents);
});
```
#### Issue: Double asset compilation
**Cause**: Both Sprockets and Propshaft trying to handle same files
**Solution**:
- Remove/rename conflicting files in `app/assets/stylesheets/`
- Use specific file names in manifest instead of `link_tree`
### 8. Testing Setup
#### GitHub Actions Workflow
Create separate workflows for different ActiveAdmin versions:
```yaml
name: Tests
on: [push, pull_request]
jobs:
test-aa4:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.2', '3.3']
rails: ['7.1', '8.0']
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install npm dependencies
run: |
cd spec/dummy
npm install
- name: Build assets
run: |
cd spec/dummy
npm run build
- name: Run tests
run: bundle exec rspec
test-legacy:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.0', '3.1']
activeadmin: ['2.14', '3.2']
# ... legacy test configuration
```
### 9. Migration Checklist
- [ ] Remove all SCSS/CSS assets from gem
- [ ] Convert JavaScript from jQuery to vanilla JS
- [ ] Create test app package.json with dependencies
- [ ] Set up Tailwind configuration
- [ ] Create CSS build process (rake task)
- [ ] Set up JavaScript build (esbuild)
- [ ] Update engine.rb for Propshaft
- [ ] Configure ActiveAdmin initializer
- [ ] Update Propshaft manifest
- [ ] Test with both Turbo and non-Turbo apps
- [ ] Update CI/CD for asset building
- [ ] Document upgrade path for gem users
### 10. User Migration Guide
Provide clear instructions for gem users:
```markdown
## Upgrading to v2.0 (ActiveAdmin 4 Support)
### Installation
1. Update your Gemfile:
```ruby
gem 'activeadmin', '~> 4.0.0.beta'
gem 'your_gem', '~> 2.0'
```
2. Install npm package:
```bash
npm install your-required-package
```
3. Update your Tailwind config to include gem styles:
```javascript
// In your tailwind.config.js
module.exports = {
content: [
// ... your existing content
'./vendor/bundle/ruby/*/gems/your_gem-*/app/**/*.rb',
]
}
```
4. Import required styles in your CSS:
```css
/* In app/assets/stylesheets/active_admin.css */
@import "your-package/dist/styles.css";
```
5. Build your assets:
```bash
rails assets:precompile
```
```
## References
- [ActiveAdmin 4.0 Beta Documentation](https://github.com/activeadmin/activeadmin/tree/master/docs)
- [Propshaft Documentation](https://github.com/rails/propshaft)
- [Tailwind CSS Rails Integration](https://tailwindcss.com/docs/guides/rails)
- [Working Example Gist](https://gist.github.com/amkisko/c704c1a6462d573dfa4820ae07d807a6)

Просмотреть файл

@@ -1,473 +0,0 @@
# ActiveAdmin Quill Editor - Rails 8 & Propshaft Migration Guide
## Executive Summary
This document outlines the necessary changes to modernize the `activeadmin_quill_editor` gem for compatibility with:
- **Rails 8.x** with Propshaft asset pipeline
- **ActiveAdmin 4.x**
- **Ruby 3.3+**
- Modern JavaScript without jQuery dependencies
**Note**: This gem already has a full test application at `spec/dummy/` and comprehensive system tests. We'll update these existing resources rather than creating new ones from scratch.
## Key Changes Overview
### 1. Asset Pipeline Migration (Propshaft)
Propshaft automatically serves assets from `vendor/assets` and `app/assets` directories in gems. The key changes:
1. **Remove Sprockets directives** - No more `//= require` statements
2. **Place precompiled assets in vendor/assets** - Propshaft serves them directly
3. **Use ES6 modules** for JavaScript initialization
4. **No asset compilation** - Serve Quill.js directly as minified files
### 2. File Structure Changes
```
activeadmin_quill_editor/
├── vendor/assets/ # Static assets served by Propshaft
│ ├── javascripts/
│ │ └── quill.min.js # Quill 2.x minified (no jQuery)
│ └── stylesheets/
│ ├── quill.snow.css # Theme CSS
│ └── quill.bubble.css # Alternative theme
├── app/assets/ # Gem-specific code
│ ├── javascripts/
│ │ └── activeadmin_quill_editor.js # ES6 initializer
│ └── stylesheets/
│ └── activeadmin_quill_editor.css # Custom styles
└── lib/
├── activeadmin/
│ └── quill_editor/
│ └── engine.rb # Rails engine configuration
└── formtastic/
└── inputs/
└── quill_editor_input.rb # Form input class
```
## Detailed Implementation
### 3. JavaScript Modernization
Replace jQuery-dependent code with vanilla JavaScript:
```javascript
// app/assets/javascripts/activeadmin_quill_editor.js
(function() {
'use strict';
const defaultToolbar = [
['bold', 'italic', 'underline'],
['link', 'blockquote', 'code-block'],
[{ 'script': 'sub' }, { 'script': 'super' }],
[{ 'align': [] }, { list: 'ordered' }, { list: 'bullet' }],
[{ 'color': [] }, { 'background': [] }],
['image'],
['clean']
];
function initQuillEditor(container) {
if (!container || container.classList.contains('quill-editor--active')) {
return;
}
const content = container.querySelector('[data-aa-quill-content]');
if (!content) return;
// Parse options from data attributes
const options = JSON.parse(container.dataset.options || '{}');
const theme = options.theme || 'snow';
const modules = options.modules || { toolbar: defaultToolbar };
// Initialize Quill
const editor = new Quill(content, {
theme: theme,
modules: modules
});
// Store reference and mark as active
container._quillEditor = editor;
container.classList.add('quill-editor--active');
// Handle form submission
const form = container.closest('form.formtastic');
if (form && !form._quillSubmitHandler) {
form._quillSubmitHandler = true;
form.addEventListener('submit', function(e) {
updateQuillInputs(form);
});
}
}
function updateQuillInputs(form) {
form.querySelectorAll('[data-aa-quill-editor]').forEach(container => {
const editor = container._quillEditor;
const input = container.querySelector('input[type="hidden"]');
if (editor && input) {
input.value = editor.root.innerHTML;
}
});
}
function initAllEditors() {
document.querySelectorAll('[data-aa-quill-editor]').forEach(initQuillEditor);
}
// Initialize on various events
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initAllEditors);
} else {
initAllEditors();
}
// Support for Turbo/Turbolinks
document.addEventListener('turbo:load', initAllEditors);
document.addEventListener('turbolinks:load', initAllEditors);
// Support for ActiveAdmin has_many fields
document.addEventListener('has_many_add:after', function(e) {
e.detail?.container?.querySelectorAll('[data-aa-quill-editor]').forEach(initQuillEditor);
});
// Public API
window.QuillEditorHelpers = {
initEditor: initQuillEditor,
initAll: initAllEditors,
getEditor: (elementOrId) => {
const element = typeof elementOrId === 'string'
? document.getElementById(elementOrId)
: elementOrId;
return element?._quillEditor;
}
};
})();
```
### 4. Updated Formtastic Input Class
```ruby
# lib/formtastic/inputs/quill_editor_input.rb
module Formtastic
module Inputs
class QuillEditorInput < Formtastic::Inputs::TextInput
def to_html
input_wrapping do
label_html <<
template.content_tag(:div, input_html_options) do
builder.hidden_field(input_name) <<
template.content_tag(:div, 'data-aa-quill-content': '1') do
object.send(method).try(:html_safe)
end
end
end
end
def input_html_options
super.tap do |options|
options['data-aa-quill-editor'] = '1'
# Merge any custom options
if options[:data] && options[:data][:options]
options['data-options'] = options[:data][:options].to_json
end
end
end
end
end
end
```
### 5. Engine Configuration for Propshaft
```ruby
# lib/activeadmin/quill_editor/engine.rb
require 'active_admin'
module ActiveAdmin
module QuillEditor
class Engine < ::Rails::Engine
engine_name 'activeadmin_quill_editor'
# Propshaft automatically includes these paths
# vendor/assets and app/assets are included by default
initializer 'activeadmin_quill_editor.assets' do |app|
# Ensure our assets are in the precompile list
if defined?(Propshaft)
app.config.assets.precompile += %w[
activeadmin_quill_editor.js
activeadmin_quill_editor.css
quill.min.js
quill.snow.css
quill.bubble.css
]
end
end
end
end
end
```
## Test Application Setup (Using Existing spec/dummy)
### 6. Update Existing Test App
The gem already has a full Rails test application at `spec/dummy/`. We need to update it for Rails 8 and Propshaft:
```ruby
# spec/dummy/config/application.rb
require_relative 'boot'
require 'rails/all'
Bundler.require(*Rails.groups)
module Dummy
class Application < Rails::Application
config.load_defaults Rails::VERSION::STRING.to_f
# Add Propshaft configuration for Rails 8
if Rails.version.to_f >= 8.0
# Propshaft is default in Rails 8
config.assets.paths << Rails.root.join("../../vendor/assets/javascripts")
config.assets.paths << Rails.root.join("../../vendor/assets/stylesheets")
else
# For Rails 7.x, explicitly use Propshaft
config.assets = Propshaft::Railtie.config.assets
end
end
end
```
### 7. Update Test App Asset Configuration
```ruby
# spec/dummy/config/initializers/assets.rb
# Add Quill editor assets to precompile list
Rails.application.config.assets.precompile += %w[
quill.min.js
quill.snow.css
quill.bubble.css
activeadmin_quill_editor.js
activeadmin_quill_editor.css
]
```
```javascript
// spec/dummy/app/assets/javascripts/active_admin.js
// For test app, import the gem's assets
//= require activeadmin_quill_editor
```
## CI/CD Configuration
### 8. GitHub Actions Workflow
```yaml
# .github/workflows/tests.yml
name: Tests
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
ruby: ['3.3', '3.4']
gemfile:
- rails_7.x_active_admin_4.x
- rails_8.x_active_admin_4.x
env:
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
RAILS_ENV: test
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: spec/dummy/package-lock.json
- name: Install npm dependencies
working-directory: spec/dummy
run: npm ci
- name: Build assets
working-directory: spec/dummy
run: npm run build
- name: Setup test database
run: bundle exec rake db:setup
- name: Run tests
run: bundle exec rspec
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
file: ./coverage/coverage.json
```
### 9. Appraisals Configuration
```ruby
# Appraisals
appraise 'rails-7.x-active-admin-4.x' do
gem 'rails', '~> 7.0'
gem 'activeadmin', '~> 4.0.0.beta'
gem 'sqlite3', '~> 2.0'
gem 'propshaft', '~> 1.0'
end
appraise 'rails-8.x-active-admin-4.x' do
gem 'rails', '~> 8.0'
gem 'activeadmin', '~> 4.0.0.beta'
gem 'sqlite3', '~> 2.0'
# Propshaft is default in Rails 8
end
```
## Migration Steps
### 10. Step-by-Step Migration Process
1. **Update gemspec dependencies**
```ruby
spec.required_ruby_version = '>= 3.3'
spec.add_dependency 'activeadmin', '~> 4.0.0.beta'
spec.add_dependency 'rails', '>= 7.0'
```
2. **Download and place Quill assets**
```bash
# Download Quill 2.x from CDN or npm
curl -o vendor/assets/javascripts/quill.min.js \
https://cdn.jsdelivr.net/npm/quill@2/dist/quill.min.js
curl -o vendor/assets/stylesheets/quill.snow.css \
https://cdn.jsdelivr.net/npm/quill@2/dist/quill.snow.css
```
3. **Update JavaScript initialization**
- Remove jQuery dependencies
- Implement vanilla JS initialization
- Add Turbo/Turbolinks support
4. **Update test suite**
- Migrate to Combustion
- Add modern browser tests
- Configure CI matrix testing
5. **Update documentation**
- Installation instructions for Propshaft
- Usage examples without jQuery
- Migration guide from old versions
## Usage in Rails 8 Application
### Installation
```ruby
# Gemfile
gem 'activeadmin_quill_editor', '~> 2.0'
```
```scss
// app/assets/stylesheets/active_admin.scss
@import 'quill.snow';
@import 'activeadmin_quill_editor';
```
```javascript
// app/javascript/active_admin.js (or equivalent)
import 'activeadmin_quill_editor';
```
### Form Usage
```ruby
form do |f|
f.inputs do
f.input :title
f.input :content, as: :quill_editor, input_html: {
data: {
options: {
theme: 'snow',
modules: {
toolbar: [
['bold', 'italic'],
['link', 'image']
]
}
}
}
}
end
f.actions
end
```
## Benefits of This Approach
1. **No NPM package needed** - Assets served directly from vendor directory
2. **Propshaft compatible** - Works with Rails 8 default asset pipeline
3. **No jQuery dependency** - Modern vanilla JavaScript
4. **Smaller bundle size** - Only ~200KB for Quill vs 450KB+ for alternatives
5. **Simple integration** - Drop-in replacement for text areas
6. **Maintained compatibility** - Works with Rails 7.x and 8.x
## Testing Locally
```bash
# Clone and setup
git clone https://github.com/yourusername/activeadmin_quill_editor.git
cd activeadmin_quill_editor
bundle install
# Run tests for specific Rails version
RAILS_VERSION=8.0 bundle exec rspec
# Or use appraisals
bundle exec appraisal rails-8.x-active-admin-4.x rspec
# Start test app server
cd spec/dummy
bundle install
bundle exec rails server
```
## Existing Test Coverage
The gem already includes comprehensive system tests at `spec/system/`:
- `quill_editor_spec.rb` - Editor functionality tests (formatting, links, etc.)
- `quill_js_spec.rb` - JavaScript API tests
Additional test cases from activeadmin_trumbowyg to consider adding:
- CSS loading verification tests
- Dark mode support tests
- Multiple editors on same page
- Has-many nested forms
- Turbo/Turbolinks compatibility tests
## Notes
- Quill.js file size: ~200KB minified (vs SunEditor's 450KB)
- No compilation step needed with Propshaft
- Assets are fingerprinted automatically by Propshaft
- Compatible with both importmap-rails and jsbundling-rails setups

Просмотреть файл

@@ -1,320 +0,0 @@
# Propshaft: A Modern Asset Pipeline for Rails
Propshaft is an asset pipeline library for Rails. It's built for an era where bundling assets to save on HTTP connections is no longer urgent, where JavaScript and CSS are either compiled by dedicated Node.js bundlers or served directly to the browsers, and where increases in bandwidth have made the need for minification less pressing. These factors allow for a dramatically simpler and faster asset pipeline compared to previous options, like [Sprockets](https://github.com/rails/sprockets-rails).
## Table of Contents
1. [Overview](#overview)
2. [Architecture](#architecture)
3. [Asset Serving in Development/Test Mode](#asset-serving-in-developmenttest-mode)
4. [Configuration and Asset Paths](#configuration-and-asset-paths)
5. [Test Environment Specifics](#test-environment-specifics)
6. [JavaScript and CSS Bundling Integration](#javascript-and-css-bundling-integration)
7. [Common Patterns and Best Practices](#common-patterns-and-best-practices)
## Overview
So that's what Propshaft doesn't do. Here's what it does provide:
1. **Configurable load path**: You can register directories from multiple places in your app and gems, and reference assets from all of these paths as though they were one.
1. **Digest stamping**: All assets in the load path will be copied (or compiled) in a precompilation step for production that also stamps all of them with a digest hash, so you can use long-expiry cache headers for better performance. The digested assets can be referred to through their logical path because the processing leaves a manifest file that provides a way to translate.
1. **Development server**: There's no need to precompile the assets in development. You can refer to them via the same asset_path helpers and they'll be served by a development server.
1. **Basic compilers**: Propshaft was explicitly not designed to provide full transpiler capabilities. You can get that better elsewhere. But it does offer a simple input->output compiler setup that by default is used to translate `url(asset)` function calls in CSS to `url(digested-asset)` instead and source mapping comments likewise.
## Architecture
### Core Components
```
Propshaft::Assembly
├── LoadPath # Asset discovery and caching
├── Resolver # Path resolution (Dynamic/Static)
│ ├── Dynamic # Development/test mode
│ └── Static # Production with manifest
├── Server # Rack middleware for asset serving
├── Processor # Precompilation and digesting
├── Compilers # Asset transformation
└── Manifest # Asset mapping and integrity hashes
```
### Key Classes
#### `Propshaft::Assembly`
Central coordinator that manages all components. Created during Rails initialization and accessible via `Rails.application.assets`.
```ruby
# Core assembly configuration
Rails.application.configure do
app.assets = Propshaft::Assembly.new(app.config.assets)
end
```
#### `Propshaft::LoadPath`
Manages asset discovery across multiple directories. Automatically includes:
- `app/assets/**/*` (application assets)
- `lib/assets/**/*` (library assets)
- `vendor/assets/**/*` (third-party assets)
- Engine assets from all loaded gems
#### `Propshaft::Resolver::Dynamic`
Used in development and test environments. Resolves assets on-demand without requiring precompilation.
#### `Propshaft::Resolver::Static`
Used in production. Relies on `.manifest.json` for fast asset resolution.
## Asset Serving in Development/Test Mode
### Dynamic Resolution Process
1. **Request Interception**: `Propshaft::Server` middleware catches requests to `/assets/*`
2. **Asset Discovery**: `LoadPath#find` searches configured paths for matching assets
3. **Compilation**: Assets pass through registered compilers
4. **Cache Headers**: Aggressive caching with ETags and immutable cache-control
5. **Response**: Compiled content served with appropriate MIME type
```ruby
# Server middleware in action (simplified)
def call(env)
if path.start_with?(@assembly.prefix) && (asset = @assembly.load_path.find(path))
[200, {
'Content-Type' => asset.content_type,
'ETag' => "\"#{asset.digest}\"",
'Cache-Control' => 'public, max-age=31536000, immutable'
}, [asset.compiled_content]]
end
end
```
### Cache Sweeping
In development/test, Propshaft monitors file changes:
```ruby
config.assets.sweep_cache = Rails.env.development?
```
When enabled, before each request:
1. File watcher checks for modifications
2. Asset cache cleared if changes detected
3. New assets discovered and cached
## Configuration and Asset Paths
### Default Configuration (from Railtie)
```ruby
config.assets.paths = [] # Auto-populated
config.assets.excluded_paths = [] # Paths to exclude
config.assets.version = "1" # Cache invalidation
config.assets.prefix = "/assets" # URL prefix
config.assets.server = Rails.env.development? || Rails.env.test?
config.assets.sweep_cache = Rails.env.development?
```
### Path Resolution Order
1. **Application paths**: `app/assets/**/*`
2. **Library paths**: `lib/assets/**/*`
3. **Vendor paths**: `vendor/assets/**/*`
4. **Engine paths**: From all loaded Rails engines/gems
Paths are automatically prioritized:
- Application assets take precedence over engine assets
- Later additions to load path have lower priority
## Installation
With Rails 8, Propshaft is the default asset pipeline for new applications. With Rails 7, you can start a new application with propshaft using `rails new myapp -a propshaft`. For existing applications, check the [upgrade guide](https://github.com/rails/propshaft/blob/main/UPGRADING.md) which contains step-by-step instructions.
## Usage
Propshaft makes all the assets from all the paths it's been configured with through `config.assets.paths` available for serving and will copy all of them into `public/assets` when precompiling. This is unlike Sprockets, which did not copy over assets that hadn't been explicitly included in one of the bundled assets.
You can however exempt directories that have been added through the `config.assets.excluded_paths`. This is useful if you're for example using `app/assets/stylesheets` exclusively as a set of inputs to a compiler like Dart Sass for Rails, and you don't want these input files to be part of the load path. (Remember you need to add full paths, like `Rails.root.join("app/assets/stylesheets")`).
These assets can be referenced through their logical path using the normal helpers like `asset_path`, `image_tag`, `javascript_include_tag`, and all the other asset helper tags. These logical references are automatically converted into digest-aware paths in production when `assets:precompile` has been run (through a JSON mapping file found in `public/assets/.manifest.json`).
## Referencing digested assets in CSS and JavaScript
Propshaft will automatically convert asset references in CSS to use the digested file names. So `background: url("/bg/pattern.svg")` is converted to `background: url("/assets/bg/pattern-2169cbef.svg")` before the stylesheet is served.
For JavaScript, you'll have to manually trigger this transformation by using the `RAILS_ASSET_URL` pseudo-method. It's used like this:
```javascript
export default class extends Controller {
init() {
this.img = RAILS_ASSET_URL("/icons/trash.svg")
}
}
```
That'll turn into:
```javascript
export default class extends Controller {
init() {
this.img = "/assets/icons/trash-54g9cbef.svg"
}
}
```
## Bypassing the digest step
If you need to put multiple files that refer to each other through Propshaft, like a JavaScript file and its source map, you have to digest these files in advance to retain stable file names. Propshaft looks for the specific pattern of `-[digest].digested.js` as the postfix to any asset file as an indication that the file has already been digested.
## Subresource Integrity (SRI)
Propshaft supports Subresource Integrity (SRI) to help protect against malicious modifications of assets. SRI allows browsers to verify that resources fetched from CDNs or other sources haven't been tampered with by checking cryptographic hashes.
### Enabling SRI
To enable SRI support, configure the hash algorithm in your Rails application:
```ruby
config.assets.integrity_hash_algorithm = "sha384"
```
Valid hash algorithms include:
- `"sha256"` - SHA-256 (most common)
- `"sha384"` - SHA-384 (recommended for enhanced security)
- `"sha512"` - SHA-512 (strongest)
### Using SRI in your views
Once configured, you can enable SRI by passing the `integrity: true` option to asset helpers:
```erb
<%= stylesheet_link_tag "application", integrity: true %>
<%= javascript_include_tag "application", integrity: true %>
```
This generates HTML with integrity hashes:
```html
<link rel="stylesheet" href="/assets/application-abc123.css"
integrity="sha384-xyz789...">
<script src="/assets/application-def456.js"
integrity="sha384-uvw012..."></script>
```
**Important**: SRI only works in secure contexts (HTTPS) or during local development. The integrity hashes are automatically omitted when serving over HTTP in production for security reasons.
### Bulk stylesheet inclusion with SRI
Propshaft extends `stylesheet_link_tag` with special symbols for bulk inclusion:
```erb
<%= stylesheet_link_tag :all, integrity: true %> <!-- All stylesheets -->
<%= stylesheet_link_tag :app, integrity: true %> <!-- Only app/assets stylesheets -->
```
## Improving performance in development
Before every request Propshaft checks if any asset was updated to decide if a cache sweep is needed. This verification is done using the application's configured file watcher which, by default, is `ActiveSupport::FileUpdateChecker`.
If you have a lot of assets in your project, you can improve performance by adding the `listen` gem to the development group in your Gemfile, and this line to the `development.rb` environment file:
```ruby
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
```
## Migrating from Sprockets
Propshaft does a lot less than Sprockets, by design, so it might well be a fair bit of work to migrate if it's even desirable. This is particularly true if you rely on Sprockets to provide any form of transpiling, like CoffeeScript or Sass, or if you rely on any gems that do. You'll need to either stop transpiling or use a Node-based transpiler, like those in [`jsbundling-rails`](https://github.com/rails/jsbundling-rails) and [`cssbundling-rails`](https://github.com/rails/cssbundling-rails).
On the other hand, if you're already bundling JavaScript and CSS through a Node-based setup, then Propshaft is going to slot in easily. Since you don't need another tool to bundle or transpile. Just to digest and serve.
But for greenfield apps using the default import-map approach, Propshaft can also work well, if you're able to deal with vanilla CSS.
## License
Propshaft is released under the [MIT License](https://opensource.org/licenses/MIT).
## Compilation and Digesting
### Asset Processing Pipeline
1. **Discovery**: `LoadPath` finds all assets matching patterns
2. **Compilation**: Each asset processed through registered compilers
3. **Digesting**: Content hash generated using SHA1 + version string
4. **Output**: Files written to `config.assets.output_path` (default: `public/assets/`)
### Built-in Compilers
#### CSS Asset URL Compiler
Transforms relative URLs to digested versions:
```css
/* Input */
background: url('./hero.jpg');
/* Output */
background: url('/assets/hero-abc123.jpg');
```
#### JavaScript Asset URL Compiler
Processes `RAILS_ASSET_URL()` pseudo-functions:
```javascript
// Input
const icon = RAILS_ASSET_URL('./icon.svg');
// Output
const icon = '/assets/icon-def456.svg';
```
#### Source Map Compiler
Updates source map references to match digested filenames.
### Manifest Generation
The manifest file (`.manifest.json`) maps logical paths to digested paths:
```json
{
"application.js": {
"digested_path": "application-abc123.js",
"integrity": "sha384-xyz789..."
}
}
```
## Asset Organization
```
app/assets/
├── builds/ # jsbundling-rails/cssbundling-rails output
│ ├── application.js
│ └── application.css
├── images/ # Static assets
│ └── logo.svg
├── stylesheets/ # SCSS source (often excluded)
│ └── application.scss
└── javascripts/ # JS source (often excluded)
└── application.js
```
## Error Handling
### Missing Asset Handling
```ruby
# Propshaft raises MissingAssetError for missing assets
begin
asset_path('nonexistent.js')
rescue Propshaft::MissingAssetError => e
Rails.logger.error "Missing asset: #{e.message}"
# Fallback logic
end
```
### Development Debugging
```ruby
# Show all available assets
rake assets:reveal
# Show asset full paths
rake assets:reveal:full
```

Просмотреть файл

@@ -1,484 +0,0 @@
# Upgrading from Sprockets to Propshaft
Propshaft has a smaller scope than Sprockets, therefore migrating to it will also require you to adopt the [jsbundling-rails](https://github.com/rails/jsbundling-rails) and [cssbundling-rails](https://github.com/rails/cssbundling-rails) gems. This guide will assume your project follows Rails 6.1 conventions of using [webpacker](https://github.com/rails/webpacker) to bundle javascript, [sass-rails](https://github.com/rails/sass-rails) to bundle css and [sprockets](https://github.com/rails/sprockets) to digest assets. Finally, you will also need [npx](https://docs.npmjs.com/cli/v7/commands/npx) version 7.1.0 or later installed.
Propshaft depends on Rails 7, so you will need to upgrade to Rails 7+ before starting the migration.
## 1. Migrate from Webpacker to jsbundling-rails
Start by following these steps:
1. Replace `webpacker` with `jsbundling-rails` in your Gemfile;
2. Run `./bin/bundle install`;
3. Run `./bin/rails javascript:install:webpack`;
4. Remove the file `config/initializers/assets.rb`;
5. Remove the file `bin/webpack`;
6. Remove the file `bin/webpack-dev-server`;
7. Remove the folder `config/webpack` (note: any custom configuration should be migrated to the new `webpack.config.js` file);
8. Remove the file `config/webpacker.yml`;
9. Replace all instances of `javascript_pack_tag` with `javascript_include_tag` and add `defer: true` to them.
After you are done you will notice that the install step added various files to your project and updated some of the existing ones.
**The new 'bin/dev' and 'Procfile.dev' files**
The `./bin/dev` file is a shell script that uses [foreman](https://github.com/ddollar/foreman) and `Procfile.dev` to start two processes in a single terminal: `rails s` and `yarn build`. The latter replaces `webpack-dev-server` for bundling and watching for changes in javascript files.
**The 'build' attribute added to package.json**
This is the command that `yarn build` will use to bundle javascript files.
**The new 'webpack.config.js' file**
In `webpacker` this file was hidden inside the gem, but now you can edit it directly. If you had custom configuration in `config/webpack` you can move them to here. Projects with multiple entrypoints will need to adjust the `entry` attribute:
```js
module.exports = {
entry: {
application: "./app/javascript/application.js",
admin: "./app/javascript/admin.js"
}
}
```
**The 'link_tree' directive added to 'app/assets/manifest.js'**
This tells Sprockets to include the files in `app/assets/builds` during `assets:precompile`. This is the folder where `yarn build` will place the bundled files, so make sure you commit it to the repository and don't delete it when cleaning assets.
**What about babel?**
If you would like to continue using babel for transpiling, you will need to configure it manually. First, open `webpack.config.js` and add this:
```js
module.exports = {
module: {
rules: [
{
test: /\.(js)$/,
exclude: /node_modules/,
use: ['babel-loader']
}
]
}
}
```
Then open `package.json` and add this:
```json
"babel": {
"presets": [
"./webpack.babel.js"
]
}
```
Finally, download [webpackers babel preset](https://github.com/rails/webpacker/blob/master/package/babel/preset.js) file and place it in the same directory as `package.json` with the name `webpack.babel.js`.
**Module resolution**
Webpacker included the `source_path` (default: `app/javascript/`) into module resolution, so a statement like `import 'channels'` imported `app/javascript/channels/`. After migrating to `jsbundling-rails` this is no longer the case. You will need to update your `webpack.config.js` to include the following if you wish to maintain that behavior:
```javascript
module.exports = {
// ...
resolve: {
modules: ["app/javascript", "node_modules"],
},
//...
}
```
Alternatively, you can change modules to use relative imports, for example:
```diff
- import 'channels'
+ import './channels'
```
### Extracting Sass/SCSS from JavaScript
In webpacker it is possible to extract Sass/SCSS from JavaScript by enabling `extract_css` in `webpacker.yml`. This allows for including those source files in JavaScript, e.g. `import '../scss/application.scss`
If you wish to keep this functionality follow these steps:
1. Run `yarn add mini-css-extract-plugin sass sass-loader css-loader`;
2. Update your `webpack.config.js` to require `mini-css-extract-plugin` and configure the loaders (see example below).
Example `webpack.config.js`:
```javascript
const path = require("path")
const webpack = require("webpack")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
module.exports = {
mode: "production",
devtool: "source-map",
entry: {
application: "./app/javascript/application.js"
},
resolve: {
modules: ["app/javascript", "node_modules"],
},
output: {
filename: "[name].js",
sourceMapFilename: "[file].map",
path: path.resolve(__dirname, "app/assets/builds"),
},
plugins: [
new MiniCssExtractPlugin(),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
})
],
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
}
```
## 2. Migrate from sass-rails to cssbundling-rails
Note: if your application used Webpacker's `extract_css` to build your CSS and did not require `sass-rails`, you can skip this section.
Start by following these steps:
1. Add `cssbundling-rails` to your Gemfile;
2. Run `./bin/bundle install`;
3. Run `./bin/rails css:install:sass`.
After you are done you will notice that the install step updated some files.
**The new process in 'Procfile.dev'**
Just like the javascript process, this one will bundle and watch for changes in css files.
**The 'build:css' attribute added to package.json**
This is the command `yarn build` will use to bundle css files.
**The 'link_tree' directive removed from 'app/assets/manifest.js'**
Now that the CSS files will be placed into `app/assets/build`, Sprockets no longer needs to worry about the `app/assets/stylesheets` folder. If you have any other `link_tree` for css files, remove them too.
### Configuring multiple entrypoints
Sprockets will only compile files in the root directories listed in `manifest.js`, but the sass package that `yarn build` uses will also check subfolders, which might cause compilation errors if your scss files are using features like `@import` and variables. This means that if you have multiple entry points in your app, you have some extra work ahead of you.
Let's assume you have the following structure in your `app/asset/stylesheets` folder:
```
stylesheets/admin.scss
stylesheets/admin/source_1.scss
stylesheets/admin/source_2.scss
stylesheets/application.scss
stylesheets/application/source_1.scss
stylesheets/application/source_2.scss
```
Start by your separating your entrypoints from your other files, and adjusting all `@import` for the new structure:
```
stylesheets/entrypoints/admin.scss
stylesheets/entrypoints/application.scss
stylesheets/sources/admin/source_1.scss
stylesheets/sources/admin/source_2.scss
stylesheets/sources/application/source_1.scss
stylesheets/sources/application/source_2.scss
```
Then adjust the `build` attribute in `package.json`:
```
"build:css": "sass ./app/assets/stylesheets/entrypoints:./app/assets/builds --no-source-map --load-path=node_modules"
```
### Deprecation warnings
Sass might raise deprecation warnings depending on what features you are using (such as division), but the messages will explain how to fix them. If you are not sure, see more details in the [official documentation](https://sass-lang.com/documentation/breaking-changes).
## 3. Migrate from Sprockets to Propshaft
Start by following these steps:
1. Remove `sprockets`, `sprockets-rails`, and `sass-rails` from the Gemfile and add `propshaft`;
2. Run `./bin/bundle install`;
3. Check your `Gemfile.lock`, repeat steps 1 and 2 for gems that list `sprockets` or `sprockets-rails` as a dependency;
4. Open `config/application.rb` and remove `config.assets.paths << Rails.root.join('app','assets')`;
5. Remove `app/assets/config/manifest.js`.
6. Replace all asset_helpers (`image_url`, `font_url`) in css files with standard `urls`.
7. If you are importing only the frameworks you need (instead of `rails/all`), remove `require "sprockets/railtie"`;
### Asset paths
Propshaft will automatically include in its search paths the folders `vendor/assets`, `lib/assets` and `app/assets` of your project and of all the gems in your Gemfile. You can see all included files by using the `reveal` rake task:
```
rake assets:reveal
```
### Asset helpers
Propshaft does not rely on asset_helpers (`asset_path`, `asset_url`, `image_url`, etc.) like Sprockets did. Instead, it will search for every `url` function in your css files, and adjust them to include the digest of the assets they reference.
Go through your css files, and make the necessary adjustments:
```diff
- background: image_url('hero.jpg');
+ background: url('/hero.jpg');
```
Notice that Propshaft's version starts with an `/` and Sprockets' version does not? That's because the latter uses **absolute paths**, and the former uses **relative paths**. To better illustrate that difference, let's assume you have the following structure:
```
assets/stylesheets/theme/main.scss
assets/images/hero.jpg
```
In Sprockets, `main.scss` can reference `hero.jpg` like this:
```css
background: image_url('hero.jpg')
```
Using the same path with `url` in Propshaft will cause it to raise an error, saying it cannot locate `theme/hero.jpg`. That's because Propshaft assumes all paths are relative to the path of the file it's processing. Since it was processing a css file inside the `theme` folder, it will also look for `hero.jpg` in the same folder.
By adding a `/` at the start of the path we are telling Propshaft to consider this path as an absolute path. While this change in behavior increases the work a bit when upgrading, it makes **external libraries like FontAwesome and Bootstrap themes work out-of-the-box**.
### Asset content
It's a common pattern in apps to inline small SVG files and low resolution versions of images that need to be displayed as quickly as possible. In Propshaft, the same line of code works for all environments:
```ruby
Rails.application.assets.load_path.find('logo.svg').content
```
As Rails escapes html tags in views by default, in order to output a rendered svg you will need to specify rails not to escape the string using [html_safe](https://api.rubyonrails.org/classes/String.html#method-i-html_safe) or [raw](https://api.rubyonrails.org/classes/ActionView/Helpers/OutputSafetyHelper.html#method-i-raw).
```ruby
Rails.application.assets.load_path.find('logo.svg').content.html_safe
raw Rails.application.assets.load_path.find('logo.svg').content
```
### Precompilation in development
Propshaft uses a dynamic assets resolver in development mode. However, when you run `assets:precompile` locally Propshaft will then switch to a static assets resolver. Therefore, changes to assets will not be observed anymore and you will have to precompile the assets each time changes are made. This is different to Sprockets.
If you wish to have dynamic assets resolver enabled again, you need to clean your target folder (usually `public/assets`) and propshaft will start serving dynamic content from source. One way to do this is to run `rails assets:clobber`.
Another way to watch changes in your CSS & JS assets is by running `bin/dev` command instead of `rails server` that not only runs the server but also keeps looking for any changes in the assets and once it detects any changes, it compiles them while the server is running. This is possible because of the `Procfile.dev`.
## 4. Specific Configuration for Test Environments
### Understanding Propshaft's Test Mode
Propshaft automatically configures itself for test environments with these defaults:
```ruby
# Automatically enabled in test environment
config.assets.server = Rails.env.test? # true for test environment
config.assets.sweep_cache = false # Disabled for faster tests
```
### Test Environment Configuration
```ruby
# config/environments/test.rb
Rails.application.configure do
# Asset server is automatically enabled - no precompilation needed
config.assets.server = true
# Optional: Add test-specific asset paths
config.assets.paths << Rails.root.join('spec/fixtures/assets')
# Optional: Disable SRI for faster test execution
config.assets.integrity_hash_algorithm = nil
# Optional: Customize asset prefix for isolated testing
# config.assets.prefix = '/test-assets'
# Performance: Use faster file watcher (if using listen gem)
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
end
```
### Testing Asset Integration
#### RSpec Configuration
```ruby
# spec/rails_helper.rb
RSpec.configure do |config|
# Ensure assets are available in feature specs
config.before(:suite) do
# Warm up asset cache for faster test execution
Rails.application.assets.load_path.assets
end
# Clean up assets between tests if needed
config.after(:each) do
# Only if you modify asset paths during tests
# Rails.application.assets.load_path.clear_cache
end
end
```
#### Testing Asset Helpers
```ruby
# spec/helpers/application_helper_spec.rb
RSpec.describe ApplicationHelper, type: :helper do
describe "asset helpers" do
it "resolves asset paths correctly" do
expect(helper.asset_path('application.js')).to match(%r{^/assets/application-\w+\.js$})
end
it "includes integrity hashes when configured" do
allow(Rails.application.config.assets).to receive(:integrity_hash_algorithm).and_return('sha384')
result = helper.javascript_include_tag('application', integrity: true)
expect(result).to include('integrity="sha384-')
end
end
end
```
#### Feature Spec Asset Testing
```ruby
# spec/features/assets_spec.rb
RSpec.describe "Asset loading", type: :feature do
it "serves JavaScript assets correctly" do
visit root_path
expect(page).to have_css('script[src*="/assets/application-"]')
end
it "serves CSS assets correctly" do
visit root_path
expect(page).to have_css('link[href*="/assets/application-"][rel="stylesheet"]')
end
end
```
### Common Test Environment Issues and Solutions
#### Issue 1: Assets Not Found in Tests
**Symptom**: `Propshaft::MissingAssetError` in test environment
**Solution**:
```ruby
# Ensure asset server is enabled in test.rb
config.assets.server = true
# Check that build artifacts exist
# For jsbundling-rails/cssbundling-rails:
bundle exec rake assets:precompile # If assets need building
```
#### Issue 2: Slow Test Startup
**Symptom**: Tests take long to start due to asset discovery
**Solution**:
```ruby
# config/environments/test.rb
# Disable sweep_cache (should be default)
config.assets.sweep_cache = false
# Exclude unnecessary paths
config.assets.excluded_paths += [
Rails.root.join("app/assets/stylesheets"), # If using cssbundling
Rails.root.join("app/javascript") # If using jsbundling
]
```
#### Issue 3: Inconsistent Asset Paths Between Environments
**Symptom**: Tests pass but development/production fails with asset references
**Solution**:
```ruby
# Use consistent asset path helpers across environments
# In views, always use:
<%= asset_path('image.png') %> # Good
# Instead of:
"/assets/image.png" # Bad - won't work with digests
```
### Performance Optimization for Tests
#### Precompile Once Strategy
For CI/CD environments where you can precompile once:
```bash
# In CI setup
bundle exec rake assets:precompile
RAILS_ENV=test bundle exec rspec
```
#### Asset Path Caching
```ruby
# config/initializers/assets.rb (test environment)
if Rails.env.test?
# Warm asset cache on initialization to avoid repeated discovery
Rails.application.config.after_initialize do
Rails.application.assets.load_path.assets
end
end
```
### Integration with Test Coverage Tools
#### SimpleCov Configuration
```ruby
# spec/spec_helper.rb
require 'simplecov'
SimpleCov.start 'rails' do
# Exclude built assets from coverage
add_filter 'app/assets/builds/'
add_filter 'vendor/assets/'
end
```
### Docker and Containerized Testing
#### Dockerfile Considerations
```dockerfile
# Dockerfile
FROM ruby:3.2
# Install Node.js for asset building
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash -
RUN apt-get install -y nodejs
# Install dependencies
COPY Gemfile Gemfile.lock package.json package-lock.json ./
RUN bundle install && npm install
# Copy source
COPY . .
# Build assets once for all test runs
RUN bundle exec rake assets:precompile
# Run tests
CMD ["bundle", "exec", "rspec"]
```
### Migration Testing Strategy
#### Before/After Asset Comparison
```ruby
# spec/migration/sprockets_to_propshaft_spec.rb
RSpec.describe "Sprockets to Propshaft migration" do
let(:expected_assets) do
%w[application.js application.css logo.png favicon.ico]
end
it "serves all expected assets" do
expected_assets.each do |asset|
expect(Rails.application.assets.resolver.resolve(asset)).to be_present
end
end
it "maintains asset content integrity" do
# Test that specific assets contain expected content
asset = Rails.application.assets.load_path.find('application.js')
expect(asset.content).to include('expected_javascript_content')
end
end
```
This comprehensive guide covers the complete migration from Sprockets to Propshaft with special attention to test environment configuration and common pitfalls.

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@@ -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.

Просмотреть файл

@@ -1,55 +0,0 @@
namespace :active_admin do
desc 'Build Active Admin Tailwind stylesheets'
task :build do
require 'fileutils'
root = File.expand_path('../../', __dir__)
# Ensure builds directory exists
FileUtils.mkdir_p(File.join(root, 'app/assets/builds'))
# Build with Tailwind CLI
command = [
'npx', 'tailwindcss',
'-i', File.join(root, 'app/assets/stylesheets/active_admin.tailwind.css'),
'-o', File.join(root, 'app/assets/builds/active_admin.css'),
'-c', File.join(root, 'tailwind.config.js'),
'-m'
]
system(*command, exception: true)
puts 'Built Active Admin CSS with Tailwind'
end
desc 'Watch Active Admin Tailwind stylesheets'
task :watch do
root = File.expand_path('../../', __dir__)
# Watch for changes
command = [
'npx', 'tailwindcss',
'--watch',
'-i', File.join(root, 'app/assets/stylesheets/active_admin.tailwind.css'),
'-o', File.join(root, 'app/assets/builds/active_admin.css'),
'-c', File.join(root, 'tailwind.config.js'),
'-m'
]
system(*command)
end
end
# Enhance existing rake tasks
if Rake::Task.task_defined?('assets:precompile')
Rake::Task['assets:precompile'].enhance(['active_admin:build'])
end
if Rake::Task.task_defined?('test:prepare')
Rake::Task['test:prepare'].enhance(['active_admin:build'])
end
if Rake::Task.task_defined?('spec:prepare')
Rake::Task['spec:prepare'].enhance(['active_admin:build'])
end
if Rake::Task.task_defined?('db:test:prepare')
Rake::Task['db:test:prepare'].enhance(['active_admin:build'])
end

Просмотреть файл

@@ -1,16 +0,0 @@
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
@import "activeadmin-tom_select/src/tom-select-tailwind.css";
/* Additional batch actions dropdown styles that aren't in the ActiveAdmin plugin */
@layer components {
.batch-actions-dropdown-toggle:disabled {
@apply opacity-50 cursor-not-allowed;
}
.batch-actions-dropdown-arrow {
@apply w-2.5 h-2.5;
}
}

Просмотреть файл

@@ -1,18 +0,0 @@
const execSync = require("node:child_process").execSync;
const activeAdminPath = execSync("bundle show activeadmin", {
encoding: "utf-8",
}).trim();
module.exports = {
content: [
`${activeAdminPath}/vendor/javascript/flowbite.js`,
`${activeAdminPath}/plugin.js`,
`${activeAdminPath}/app/views/**/*.{arb,erb,html,rb}`,
"./app/admin/**/*.{arb,erb,html,rb}",
"./app/views/active_admin/**/*.{arb,erb,html,rb}",
"./app/views/admin/**/*.{arb,erb,html,rb}",
"./app/views/layouts/active_admin*.{erb,html}",
"./app/assets/controllers/active_admin/**/*.js",
],
darkMode: "selector"
};

Просмотреть файл

@@ -1,308 +0,0 @@
# Quill Editor Migration Guide for ActiveAdmin 4
## Overview
This guide helps you migrate the activeadmin-quill_editor gem to support ActiveAdmin 4 with modern Rails 8+ and Propshaft asset pipeline.
## Key Changes Made
### 1. Removed jQuery Dependency
**Before**: JavaScript relied on jQuery for initialization and DOM manipulation
**After**: Pure vanilla JavaScript with modern event listeners
### 2. Asset Pipeline Updates
**Before**: Sprockets-based asset compilation with CDN dependencies
**After**: Propshaft-compatible with NPM-based Quill installation
### 3. Ruby and Rails Version Requirements
- **Minimum Ruby**: 3.2+ (previously 3.0+)
- **Rails Support**: 7.0+ with ActiveAdmin 2.9-4.x
- **ActiveAdmin 4**: Full support with Propshaft
## Installation & Setup
### Step 1: Update Your Gemfile
```ruby
gem 'activeadmin_quill_editor', '~> 2.0'
```
### Step 2: Install Quill via NPM
```bash
# In your Rails app root
npm install quill@^2.0.2
```
Or add to `package.json`:
```json
{
"dependencies": {
"quill": "^2.0.2"
}
}
```
### Step 3: Configure JavaScript (Rails 8 with esbuild)
Create or update `app/javascript/active_admin.js`:
```javascript
// Import ActiveAdmin (if using AA4)
import '@activeadmin/activeadmin';
// Import Quill
import Quill from 'quill';
window.Quill = Quill;
// The gem's initialization will auto-load when included
```
### Step 4: Configure CSS
#### With Tailwind CSS (ActiveAdmin 4)
In `app/assets/stylesheets/active_admin.tailwind.css`:
```css
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
/* Quill styles */
@import "quill/dist/quill.snow.css";
@import "quill/dist/quill.bubble.css";
```
#### With Sass/SCSS (Legacy)
In `app/assets/stylesheets/active_admin.scss`:
```scss
@import "active_admin/base";
@import "quill/dist/quill.snow";
// Optional bubble theme
@import "quill/dist/quill.bubble";
```
### Step 5: Build Configuration
#### esbuild.config.js
```javascript
const esbuild = require('esbuild');
const path = require('path');
const config = {
entryPoints: ['app/javascript/active_admin.js'],
bundle: true,
sourcemap: true,
format: 'iife',
outdir: 'app/assets/builds',
publicPath: '/assets',
};
// Build or watch
if (process.argv.includes('--watch')) {
esbuild.context(config).then(ctx => {
ctx.watch();
});
} else {
esbuild.build(config);
}
```
#### package.json scripts
```json
{
"scripts": {
"build:js": "node esbuild.config.js",
"build:css": "tailwindcss -i app/assets/stylesheets/active_admin.tailwind.css -o app/assets/builds/active_admin.css -m",
"build": "npm run build:js && npm run build:css"
}
}
```
## Usage
### Basic Usage
```ruby
# app/admin/posts.rb
ActiveAdmin.register Post do
permit_params :title, :content, :description
form do |f|
f.inputs do
f.input :title
f.input :content, as: :quill_editor
f.input :description, as: :quill_editor, input_html: {
data: {
options: {
theme: 'snow',
modules: {
toolbar: [
['bold', 'italic', 'underline'],
['link', 'image'],
[{ list: 'ordered' }, { list: 'bullet' }]
]
}
}
}
}
end
f.actions
end
end
```
### Custom Toolbar Configuration
```ruby
f.input :content, as: :quill_editor, input_html: {
data: {
options: {
theme: 'snow', # or 'bubble'
modules: {
toolbar: [
[{ 'header': [1, 2, 3, false] }],
['bold', 'italic', 'underline', 'strike'],
[{ 'color': [] }, { 'background': [] }],
[{ 'script': 'sub' }, { 'script': 'super' }],
['blockquote', 'code-block'],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'align': [] }],
['link', 'image', 'video'],
['clean']
]
}
}
}
}
```
### Image Upload Support (Optional)
```bash
npm install quill-image-uploader
```
Configure in your form:
```ruby
f.input :content, as: :quill_editor, input_html: {
data: {
plugins: {
image_uploader: {
server_url: '/admin/upload',
field_name: 'file'
}
}
}
}
```
## JavaScript API
The gem exposes these global functions:
```javascript
// Get all Quill editor instances
const editors = getQuillEditors();
// Get editor by index (0-based)
const firstEditor = getQuillEditorByIndex(0);
// Get editor by element ID
const editor = getQuillEditorByElementId('post_content');
// Access Quill API directly
editor.getContents();
editor.setText('New content');
editor.format('bold', true);
```
## Migration from Legacy Versions
### Removing jQuery Dependencies
**Old initialization (jQuery)**:
```javascript
$(document).ready(function() {
// Initialization code
});
```
**New initialization (Vanilla JS)**:
```javascript
// Automatically handled by the gem
// Or manually initialize:
document.addEventListener('DOMContentLoaded', function() {
// Custom initialization if needed
});
```
### Asset Pipeline Changes
**Old (Sprockets)**:
```javascript
//= require activeadmin/quill_editor/quill
//= require activeadmin/quill_editor_input
```
**New (Propshaft/esbuild)**:
```javascript
import Quill from 'quill';
// Gem's initialization auto-loads
```
## Troubleshooting
### Issue: Quill not initializing
**Solution**: Ensure JavaScript is properly included:
- Check that `window.Quill` is defined
- Verify the gem's JS is loaded after Quill
- Check browser console for errors
### Issue: Styles not loading
**Solution**: Verify CSS imports:
- Ensure Quill CSS is imported
- Check that Tailwind processes the styles
- Verify no CSS conflicts with ActiveAdmin
### Issue: Form submission not saving content
**Solution**: The gem automatically handles form submission. Check:
- Hidden input field is present in HTML
- No JavaScript errors preventing update
- Strong parameters permit the field
## Testing Your Implementation
### RSpec System Tests
```ruby
# spec/system/admin_posts_spec.rb
require 'rails_helper'
RSpec.describe 'Admin Posts', type: :system do
it 'creates a post with Quill editor' do
visit '/admin/posts/new'
# Fill in Quill editor
within '[data-aa-quill-editor]' do
find('.ql-editor').set('Test content')
end
click_button 'Create Post'
expect(page).to have_content('Post was successfully created')
expect(Post.last.content).to include('Test content')
end
end
```
## Version Compatibility Matrix
| Gem Version | ActiveAdmin | Rails | Ruby | Quill |
|-------------|-------------|-------|------|-------|
| 2.0.x | 2.9-4.x | 7.0-8.x | 3.2+ | 2.x |
| 1.x | 2.x-3.x | 6.1-7.x | 3.0+ | 1.x |
## Additional Resources
- [Quill Documentation](https://quilljs.com/)
- [ActiveAdmin 4 Migration Guide](https://github.com/activeadmin/activeadmin/wiki)
- [Propshaft Documentation](https://github.com/rails/propshaft)
- [Rails 8 Asset Pipeline Guide](https://guides.rubyonrails.org/asset_pipeline.html)
## Support
For issues or questions:
- GitHub Issues: https://github.com/rs-pro/activeadmin-quill_editor/issues
- ActiveAdmin Community: https://github.com/activeadmin/activeadmin/discussions

Просмотреть файл

@@ -1,184 +0,0 @@
# Tom Select Migration Summary
## Overview
We successfully migrated ActiveAdmin Searchable Select from Select2 (jQuery-based) to Tom Select (vanilla JS, TypeScript-ready) with Tailwind CSS 4 support.
## Key Changes Made
### 1. Package Dependencies
**Removed:**
- `jquery` peer dependency
- `select2` peer dependency
**Added:**
- `tom-select: ^2.4.3` peer dependency
### 2. JavaScript Changes
#### `/src/index.js`
- Complete rewrite without jQuery dependency
- Uses native `fetch()` for AJAX requests
- Tom Select initialization with proper option mapping
- Handles Select2 → Tom Select option conversion (id/text → valueField/labelField)
#### Removed Legacy Files:
- `/src/searchable_select/init.js` - Legacy compatibility file removed
- `/spec/internal/inject-jquery.js` - jQuery injection hack removed
- `/spec/internal/build_activeadmin_css.js` - Old CSS build hack removed
### 3. CSS/Styling Changes
#### New Files Created:
- `/src/tom-select-tailwind.css` - Complete Tom Select styles with Tailwind classes (consolidated single file)
#### Package Exports Updated:
```json
"exports": {
"./tom-select-tailwind": "./src/tom-select-tailwind.css"
}
```
#### Removed Files:
- `/src/searchable_select.css` - Consolidated into tom-select-tailwind.css
- All legacy Select2 CSS imports
### 4. Build Process (Tailwind 3)
#### New Test App Structure:
```
/spec/internal/
├── tailwind.config.js # Tailwind 3 config
├── app/assets/stylesheets/
│ └── active_admin.tailwind.css # Main CSS entry with Tom Select styles
├── build-css.js # Node script for CSS build
├── esbuild.config.js # JavaScript build config
└── package.json # Simplified scripts
```
#### Build Commands:
- `npm run build:css` → Runs Tailwind CSS via `build-css.js`
- `npm run build:js` → Runs esbuild for JavaScript bundling
- `npm run build` → Builds both JS and CSS
#### CSS Build Process Fix:
- Integrated comprehensive ActiveAdmin styles from docs/tailwind-4 setup
- Included all ActiveAdmin component styles (panels, data tables, filters, forms, etc.)
- Tom Select styles are imported at the end of the CSS file
- All styles are properly processed by Tailwind CSS and included in the final build
- Fixed styling issues that were breaking ActiveAdmin UI components
### 5. Test Updates
#### CSS Class Changes:
| Select2 | Tom Select |
|---------|------------|
| `.select2-container` | `.ts-wrapper` or `.ts-control` |
| `.select2-dropdown` | `.ts-dropdown` |
| `.select2-results__option` | `.ts-dropdown .option` |
| `.select2-selection` | `.ts-control .item` |
| `.select2-search__field` | `.ts-control input` |
#### Helper Method Updates in Tests:
- `expand_select_box`: Now clicks `.ts-control`
- `enter_search_term`: Targets `.ts-control input`
- `select_box_items`: Finds `.ts-dropdown .option`
- `finished_all_ajax_requests`: No longer uses jQuery.active
### 6. Documentation Structure
#### Example Files (with credits):
`/docs/tailwind-4/` - Example Tailwind 4 setup files
- Credit: https://gist.github.com/amkisko/af1b2f7dc4f0f941437ea16400277864
### 7. Migration Path for Users
Users will need to:
1. Update their `Gemfile` to use the new version
2. Remove jQuery and Select2 dependencies
3. Add Tom Select dependency: `npm install tom-select@^2.4.3`
4. Update their CSS imports to use Tom Select styles
5. If using Tailwind, import our tom-select-tailwind styles
6. Update any custom JavaScript that referenced Select2 APIs
### 8. Breaking Changes
1. **No jQuery Required**: Apps no longer need jQuery for searchable selects
2. **CSS Classes Changed**: All Select2 classes replaced with Tom Select equivalents
3. **JavaScript API Different**: Tom Select has different initialization and options
4. **Legacy init.js Removed**: No backward compatibility layer
### 9. Benefits of Migration
1. **No jQuery Dependency**: Reduces bundle size significantly
2. **Modern JavaScript**: ES6+ modules, TypeScript support
3. **Better Performance**: Tom Select is lighter and faster
4. **Tailwind 4 Ready**: Native Tailwind utility classes
5. **Future-Proof**: Active development, modern architecture
### 10. Files to Commit
**Modified:**
- `/package.json` - Updated dependencies and exports
- `/src/index.js` - Rewritten for Tom Select
- `/spec/features/*.rb` - Updated test selectors
- `/spec/internal/package.json` - Removed jQuery, added Tom Select
- `/spec/internal/app/js/active_admin.js` - Tom Select import
**Created:**
- `/src/tom-select-tailwind.css`
- `/src/searchable_select.css`
- `/spec/internal/config/tailwind-active_admin.config.js`
- `/spec/internal/app/assets/stylesheets/active_admin.tailwind.css`
- `/spec/internal/lib/tasks/active_admin.rake`
**Deleted:**
- `/src/searchable_select/` directory
- `/spec/internal/inject-jquery.js`
- `/spec/internal/build_activeadmin_css.js`
- `/spec/internal/tailwind-active_admin.config.js` (old location)
### 11. Testing Status
**Tests Fixed and Working:**
- All JavaScript initialization tests passing
- Tom Select properly initializes in test environment
- Clear button functionality working for all searchable selects
- Assets properly served in test environment
**Test Environment Setup:**
- Assets must be built: `npm run build:js` and `bundle exec rake active_admin:build`
- Assets copied to public directory for test environment:
```bash
mkdir -p public/javascripts public/stylesheets
cp app/assets/builds/active_admin.js public/javascripts/
cp app/assets/builds/active_admin.css public/stylesheets/
```
- Tests use Playwright driver for modern JavaScript support
**Remaining Test Issues (4 failures):**
- AJAX options not loading properly in some integration tests
- Dropdown visibility detection needs adjustment for Tom Select
- Search input focus/activation needs refinement
### 12. Key Implementation Details
#### Clear Button Feature:
- All searchable selects are clearable by default
- Implemented via `data-clearable="true"` attribute
- Tom Select's `clear_button` plugin automatically added
- Clear button positioned at `right: 2rem` for better UX
- Can be disabled by setting `clearable: false` in Ruby options
#### JavaScript Module Export:
- Main module exports both `setupAutoInit` and `initSearchableSelects`
- Functions made globally available in test environment via `window` object
- Auto-initialization on DOMContentLoaded, Turbo load, and has_many_add events
### 13. Next Steps
1. ✅ Complete test fixes for remaining failures (mostly done)
2. Update README.md with new installation instructions
3. Create migration guide at `/docs/guide-update-your-app.md`
4. Version bump to 5.0.0 (major version due to breaking changes)
5. Test with real ActiveAdmin applications
6. Consider adding TypeScript definitions for better IDE support

Просмотреть файл

@@ -1,3 +0,0 @@
alias ls='ls --color'
alias ll='ls -l'
alias la='ls -la'

Просмотреть файл

@@ -1,7 +0,0 @@
COMPOSE_PROJECT_NAME=activeadmin_quill_editor
BUNDLER_VERSION=2.5.23
SERVER_PORT=4000
UID=1000
GID=1000

Просмотреть файл

@@ -1,31 +1,21 @@
ARG RUBY_IMAGE=ruby:3
FROM ${RUBY_IMAGE}
ENV DEBIAN_FRONTEND=noninteractive
ARG UID
ENV DEVEL=1
ENV LANG=C.UTF-8
ENV RAILS_ENV=development
RUN apt-get update -qq
RUN apt-get install -yqq --no-install-recommends build-essential chromium less libyaml-dev nano netcat-traditional pkg-config
RUN DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends build-essential chromium libyaml-dev nano
ARG BUNDLER_VERSION
RUN gem install bundler -v ${BUNDLER_VERSION}
RUN gem install bundler
RUN echo 'gem: --no-document' > /etc/gemrc
ARG UID
RUN useradd -u $UID --shell /bin/bash app
RUN useradd -u ${UID} --shell /bin/bash app
RUN mkdir -p /home/app && chown -R app:app /home/app
RUN chown -R app /usr/local/bundle
ARG RAILS_VERSION
ENV RAILS_VERSION=$RAILS_VERSION
ARG ACTIVEADMIN_VERSION
ENV ACTIVEADMIN_VERSION=$ACTIVEADMIN_VERSION
WORKDIR /app
USER ${UID}
COPY . /app
RUN bundle install
RUN chown -R app:app /usr/local/bundle
RUN ln -s /app/extra/.bashrc /home/app/.bashrc

Просмотреть файл

@@ -1,6 +0,0 @@
# Ignore everything but the required files for bundle install
/**/*
!/*.gemspec
!/Gemfile
!/lib

18
extra/Dockerfile_alpine Обычный файл
Просмотреть файл

@@ -0,0 +1,18 @@
FROM ruby:3.3-alpine
ARG UID
ENV DEVEL=1
ENV LANG=C.UTF-8
ENV RAILS_ENV=development
RUN apk update && apk add --no-cache build-base chromium tzdata yaml-dev
RUN gem install bundler
RUN echo 'gem: --no-document' > /etc/gemrc
RUN adduser -u ${UID} -D app
RUN mkdir -p /home/app && chown -R app:app /home/app
RUN chown -R app /usr/local/bundle
COPY . /app

21
extra/README.md Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
# Development
Overcommit can be used to ensure that Conventional commits are good.
## Releases
```sh
# Update version.rb with the new version
# Update the gemfiles:
bin/appraisal
```
## Testing
```sh
# Running specs using a specific configuration:
bin/appraisal rails60-activeadmin22 rspec
# Using latest activeadmin version:
bin/appraisal rails60-activeadmin rspec
# See gemfiles for more configurations
```

Просмотреть файл

@@ -4,3 +4,5 @@ export DEVEL=1
export RAILS_VERSION=7.2.2.1
export ACTIVEADMIN_VERSION=3.3.0
export RAILS_ENV=development

Просмотреть файл

@@ -1,50 +0,0 @@
## Development
### Dev setup
There are 2 ways to interact with this project:
1) Using Docker:
```sh
make up # starts the dev services (optional env vars: RUBY / RAILS / ACTIVEADMIN)
make specs # run the tests (after up)
make lint # run the linters (after up)
make server # run the server (after up)
make shell # open a shell (after up)
make down # cleanup (after up)
# Example using specific versions:
RUBY=3.2 RAILS=7.1 ACTIVEADMIN=3.2.0 make up
```
2) With a local setup:
```sh
# Dev setup (set the required envs):
source extra/dev_setup.sh
# Install dependencies:
bundle update
# Run server (or any command):
bin/rails s
# To try different versions of Rails/ActiveAdmin edit extra/dev_setup.sh
```
### Update the editor
- Update the CSS/JS editor assets:
```sh
wget "https://cdn.jsdelivr.net/npm/quill@2/dist/quill.snow.css" -O "app/assets/stylesheets/activeadmin/quill_editor/quill.snow.css"
wget "https://cdn.jsdelivr.net/npm/quill@2/dist/quill.bubble.css" -O "app/assets/stylesheets/activeadmin/quill_editor/quill.bubble.css"
wget "https://cdn.jsdelivr.net/npm/quill@2/dist/quill.core.css" -O "app/assets/stylesheets/activeadmin/quill_editor/quill.core.css"
wget "https://cdn.jsdelivr.net/npm/quill@2/dist/quill.js" -O "app/assets/javascripts/activeadmin/quill_editor/quill.js"
wget "https://cdn.jsdelivr.net/npm/quill@2/dist/quill.core.js" -O "app/assets/javascripts/activeadmin/quill_editor/quill.core.js"
wget "https://github.com/valentsea/quill2-image-uploader/raw/refs/heads/master/dist/quill.imageUploader.min.js" -O "app/assets/javascripts/activeadmin/quill.imageUploader.min.js"
wget "https://github.com/valentsea/quill2-image-uploader/raw/refs/heads/master/dist/quill.imageUploader.min.css" -O "app/assets/stylesheets/activeadmin/quill.imageUploader.min.css"
```
- Check the changes, most of them should be for updated files plus some new / removed file

Просмотреть файл

@@ -1,19 +0,0 @@
services:
app:
build:
context: ..
dockerfile: extra/Dockerfile
args:
BUNDLER_VERSION: ${BUNDLER_VERSION}
RUBY_IMAGE: ruby:${RUBY:-3.4}-slim
RAILS_VERSION: ${RAILS:-}
ACTIVEADMIN_VERSION: ${ACTIVEADMIN:-}
UID: ${UID}
user: ${UID}:${GID}
ports:
- ${SERVER_PORT}:${SERVER_PORT}
working_dir: /app
volumes:
- ..:/app
stdin_open: true
tty: true

8
extra/entrypoint.sh Обычный файл
Просмотреть файл

@@ -0,0 +1,8 @@
echo "> Install dependencies"
rm -f Gemfile.lock && bundle install
echo "> Run pending migrations"
cd spec/dummy && bundle exec rails db:migrate
echo "> Start Rails server"
cd /app && rm -f spec/dummy/tmp/pids/server.pid && bundle exec rails s -b 0.0.0.0

28
gemfiles/rails61_activeadmin.gemfile Обычный файл
Просмотреть файл

@@ -0,0 +1,28 @@
# This file was generated by Appraisal
source "https://rubygems.org"
gem "sqlite3"
gem "bigdecimal"
gem "mutex_m"
gem "puma"
gem "sassc"
gem "sprockets-rails"
gem "capybara"
gem "cuprite"
gem "rspec_junit_formatter"
gem "rspec-rails"
gem "rspec-retry"
gem "fasterer"
gem "rubocop"
gem "rubocop-capybara"
gem "rubocop-packaging"
gem "rubocop-performance"
gem "rubocop-rails"
gem "rubocop-rspec"
gem "rubocop-rspec_rails"
gem "pry-rails"
gem "activeadmin"
gem "rails", "~> 6.1.0"
gemspec path: "../"

352
gemfiles/rails61_activeadmin.gemfile.lock Обычный файл
Просмотреть файл

@@ -0,0 +1,352 @@
PATH
remote: ..
specs:
activeadmin_quill_editor (1.3.0)
activeadmin (>= 2.9, < 4)
GEM
remote: https://rubygems.org/
specs:
actioncable (6.1.7.7)
actionpack (= 6.1.7.7)
activesupport (= 6.1.7.7)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (6.1.7.7)
actionpack (= 6.1.7.7)
activejob (= 6.1.7.7)
activerecord (= 6.1.7.7)
activestorage (= 6.1.7.7)
activesupport (= 6.1.7.7)
mail (>= 2.7.1)
actionmailer (6.1.7.7)
actionpack (= 6.1.7.7)
actionview (= 6.1.7.7)
activejob (= 6.1.7.7)
activesupport (= 6.1.7.7)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (6.1.7.7)
actionview (= 6.1.7.7)
activesupport (= 6.1.7.7)
rack (~> 2.0, >= 2.0.9)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.1.7.7)
actionpack (= 6.1.7.7)
activerecord (= 6.1.7.7)
activestorage (= 6.1.7.7)
activesupport (= 6.1.7.7)
nokogiri (>= 1.8.5)
actionview (6.1.7.7)
activesupport (= 6.1.7.7)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activeadmin (3.2.0)
arbre (~> 1.2, >= 1.2.1)
formtastic (>= 3.1)
formtastic_i18n (>= 0.4)
inherited_resources (~> 1.7)
jquery-rails (>= 4.2)
kaminari (>= 1.2.1)
railties (>= 6.1)
ransack (>= 4.0)
activejob (6.1.7.7)
activesupport (= 6.1.7.7)
globalid (>= 0.3.6)
activemodel (6.1.7.7)
activesupport (= 6.1.7.7)
activerecord (6.1.7.7)
activemodel (= 6.1.7.7)
activesupport (= 6.1.7.7)
activestorage (6.1.7.7)
actionpack (= 6.1.7.7)
activejob (= 6.1.7.7)
activerecord (= 6.1.7.7)
activesupport (= 6.1.7.7)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (6.1.7.7)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
appraisal (2.5.0)
bundler
rake
thor (>= 0.14.0)
arbre (1.7.0)
activesupport (>= 3.0.0)
ruby2_keywords (>= 0.0.2)
ast (2.4.2)
bigdecimal (3.1.9)
builder (3.2.4)
capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
coderay (1.1.3)
concurrent-ruby (1.2.3)
crass (1.0.6)
cuprite (0.15)
capybara (~> 3.0)
ferrum (~> 0.14.0)
date (3.3.4)
diff-lcs (1.5.1)
erubi (1.12.0)
fasterer (0.11.0)
ruby_parser (>= 3.19.1)
ferrum (0.14)
addressable (~> 2.5)
concurrent-ruby (~> 1.1)
webrick (~> 1.7)
websocket-driver (>= 0.6, < 0.8)
ffi (1.16.3)
formtastic (5.0.0)
actionpack (>= 6.0.0)
formtastic_i18n (0.7.0)
globalid (1.2.1)
activesupport (>= 6.1)
has_scope (0.8.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
inherited_resources (1.14.0)
actionpack (>= 6.0)
has_scope (>= 0.6)
railties (>= 6.0)
responders (>= 2)
jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.7.1)
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
kaminari-activerecord (= 1.2.2)
kaminari-core (= 1.2.2)
kaminari-actionview (1.2.2)
actionview
kaminari-core (= 1.2.2)
kaminari-activerecord (1.2.2)
activerecord
kaminari-core (= 1.2.2)
kaminari-core (1.2.2)
language_server-protocol (3.17.0.3)
loofah (2.22.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
mini_mime (>= 0.1.1)
net-imap
net-pop
net-smtp
marcel (1.0.2)
matrix (0.4.2)
method_source (1.0.0)
mini_mime (1.1.5)
minitest (5.22.2)
mutex_m (0.3.0)
net-imap (0.4.10)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
net-smtp (0.4.0.1)
net-protocol
nio4r (2.7.0)
nokogiri (1.16.2-arm64-darwin)
racc (~> 1.4)
nokogiri (1.16.2-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.16.2-x86_64-linux)
racc (~> 1.4)
parallel (1.24.0)
parser (3.3.0.5)
ast (~> 2.4.1)
racc
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
public_suffix (5.0.4)
puma (6.4.2)
nio4r (~> 2.0)
racc (1.7.3)
rack (2.2.8.1)
rack-test (2.1.0)
rack (>= 1.3)
rails (6.1.7.7)
actioncable (= 6.1.7.7)
actionmailbox (= 6.1.7.7)
actionmailer (= 6.1.7.7)
actionpack (= 6.1.7.7)
actiontext (= 6.1.7.7)
actionview (= 6.1.7.7)
activejob (= 6.1.7.7)
activemodel (= 6.1.7.7)
activerecord (= 6.1.7.7)
activestorage (= 6.1.7.7)
activesupport (= 6.1.7.7)
bundler (>= 1.15.0)
railties (= 6.1.7.7)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
railties (6.1.7.7)
actionpack (= 6.1.7.7)
activesupport (= 6.1.7.7)
method_source
rake (>= 12.2)
thor (~> 1.0)
rainbow (3.1.1)
rake (13.1.0)
ransack (4.1.1)
activerecord (>= 6.1.5)
activesupport (>= 6.1.5)
i18n
regexp_parser (2.9.0)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
rexml (3.2.6)
rspec-core (3.13.0)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (6.1.1)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
rspec-core (~> 3.12)
rspec-expectations (~> 3.12)
rspec-mocks (~> 3.12)
rspec-support (~> 3.12)
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.13.1)
rspec_junit_formatter (0.6.0)
rspec-core (>= 2, < 4, != 2.12.0)
rubocop (1.60.2)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.30.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
parser (>= 3.2.1.0)
rubocop-capybara (2.20.0)
rubocop (~> 1.41)
rubocop-factory_bot (2.25.1)
rubocop (~> 1.41)
rubocop-packaging (0.5.2)
rubocop (>= 1.33, < 2.0)
rubocop-performance (1.20.2)
rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rails (2.23.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rspec (2.26.1)
rubocop (~> 1.40)
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
rubocop-rspec_rails (2.28.3)
rubocop (~> 1.40)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
ruby_parser (3.21.0)
racc (~> 1.5)
sexp_processor (~> 4.16)
sassc (2.4.0)
ffi (~> 1.9)
sexp_processor (4.17.1)
sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
sprockets-rails (3.4.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets (>= 3.0.0)
sqlite3 (1.7.2-arm64-darwin)
sqlite3 (1.7.2-x86_64-darwin)
sqlite3 (1.7.2-x86_64-linux)
thor (1.3.0)
timeout (0.4.1)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
webrick (1.8.1)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.13)
PLATFORMS
arm64-darwin-22
arm64-darwin-23
x86_64-darwin-21
x86_64-linux
DEPENDENCIES
activeadmin
activeadmin_quill_editor!
appraisal (~> 2.4)
bigdecimal
capybara
cuprite
fasterer
mutex_m
pry-rails
puma
rails (~> 6.1.0)
rspec-rails
rspec-retry
rspec_junit_formatter
rubocop
rubocop-capybara
rubocop-packaging
rubocop-performance
rubocop-rails
rubocop-rspec
rubocop-rspec_rails
sassc
sprockets-rails
sqlite3
BUNDLED WITH
2.3.8

Просмотреть файл

@@ -2,20 +2,17 @@
source "https://rubygems.org"
gem "rails", "~> 6.1.0"
gem "activeadmin", "~> 2.9.0"
gem "sqlite3"
gem "concurrent-ruby", "1.3.4"
gem "bigdecimal"
gem "csv"
gem "mutex_m"
gem "puma"
gem "sassc"
gem "sprockets-rails"
gem "capybara"
gem "cuprite"
gem "rspec_junit_formatter"
gem "rspec-rails"
gem "simplecov", require: false
gem "super_diff"
gem "rspec-retry"
gem "fasterer"
gem "rubocop"
gem "rubocop-capybara"
@@ -24,9 +21,8 @@ gem "rubocop-performance"
gem "rubocop-rails"
gem "rubocop-rspec"
gem "rubocop-rspec_rails"
gem "appraisal"
gem "pry-rails"
gem "sassc"
gem "sprockets-rails"
gem "activeadmin", "~> 2.9.0"
gem "rails", "~> 6.1.0"
gemspec path: "../"

352
gemfiles/rails61_activeadmin29.gemfile.lock Обычный файл
Просмотреть файл

@@ -0,0 +1,352 @@
PATH
remote: ..
specs:
activeadmin_quill_editor (1.3.0)
activeadmin (>= 2.9, < 4)
GEM
remote: https://rubygems.org/
specs:
actioncable (6.1.7.7)
actionpack (= 6.1.7.7)
activesupport (= 6.1.7.7)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (6.1.7.7)
actionpack (= 6.1.7.7)
activejob (= 6.1.7.7)
activerecord (= 6.1.7.7)
activestorage (= 6.1.7.7)
activesupport (= 6.1.7.7)
mail (>= 2.7.1)
actionmailer (6.1.7.7)
actionpack (= 6.1.7.7)
actionview (= 6.1.7.7)
activejob (= 6.1.7.7)
activesupport (= 6.1.7.7)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (6.1.7.7)
actionview (= 6.1.7.7)
activesupport (= 6.1.7.7)
rack (~> 2.0, >= 2.0.9)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.1.7.7)
actionpack (= 6.1.7.7)
activerecord (= 6.1.7.7)
activestorage (= 6.1.7.7)
activesupport (= 6.1.7.7)
nokogiri (>= 1.8.5)
actionview (6.1.7.7)
activesupport (= 6.1.7.7)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activeadmin (2.9.0)
arbre (~> 1.2, >= 1.2.1)
formtastic (>= 3.1, < 5.0)
formtastic_i18n (~> 0.4)
inherited_resources (~> 1.7)
jquery-rails (~> 4.2)
kaminari (~> 1.0, >= 1.2.1)
railties (>= 5.2, < 6.2)
ransack (~> 2.1, >= 2.1.1)
activejob (6.1.7.7)
activesupport (= 6.1.7.7)
globalid (>= 0.3.6)
activemodel (6.1.7.7)
activesupport (= 6.1.7.7)
activerecord (6.1.7.7)
activemodel (= 6.1.7.7)
activesupport (= 6.1.7.7)
activestorage (6.1.7.7)
actionpack (= 6.1.7.7)
activejob (= 6.1.7.7)
activerecord (= 6.1.7.7)
activesupport (= 6.1.7.7)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (6.1.7.7)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
appraisal (2.5.0)
bundler
rake
thor (>= 0.14.0)
arbre (1.7.0)
activesupport (>= 3.0.0)
ruby2_keywords (>= 0.0.2)
ast (2.4.2)
bigdecimal (3.1.9)
builder (3.2.4)
capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
coderay (1.1.3)
concurrent-ruby (1.2.3)
crass (1.0.6)
cuprite (0.15)
capybara (~> 3.0)
ferrum (~> 0.14.0)
date (3.3.4)
diff-lcs (1.5.1)
erubi (1.12.0)
fasterer (0.11.0)
ruby_parser (>= 3.19.1)
ferrum (0.14)
addressable (~> 2.5)
concurrent-ruby (~> 1.1)
webrick (~> 1.7)
websocket-driver (>= 0.6, < 0.8)
ffi (1.16.3)
formtastic (4.0.0)
actionpack (>= 5.2.0)
formtastic_i18n (0.7.0)
globalid (1.2.1)
activesupport (>= 6.1)
has_scope (0.8.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
inherited_resources (1.14.0)
actionpack (>= 6.0)
has_scope (>= 0.6)
railties (>= 6.0)
responders (>= 2)
jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.7.1)
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
kaminari-activerecord (= 1.2.2)
kaminari-core (= 1.2.2)
kaminari-actionview (1.2.2)
actionview
kaminari-core (= 1.2.2)
kaminari-activerecord (1.2.2)
activerecord
kaminari-core (= 1.2.2)
kaminari-core (1.2.2)
language_server-protocol (3.17.0.3)
loofah (2.22.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
mini_mime (>= 0.1.1)
net-imap
net-pop
net-smtp
marcel (1.0.2)
matrix (0.4.2)
method_source (1.0.0)
mini_mime (1.1.5)
minitest (5.22.2)
mutex_m (0.3.0)
net-imap (0.4.10)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
net-smtp (0.4.0.1)
net-protocol
nio4r (2.7.0)
nokogiri (1.16.2-arm64-darwin)
racc (~> 1.4)
nokogiri (1.16.2-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.16.2-x86_64-linux)
racc (~> 1.4)
parallel (1.24.0)
parser (3.3.0.5)
ast (~> 2.4.1)
racc
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
public_suffix (5.0.4)
puma (6.4.2)
nio4r (~> 2.0)
racc (1.7.3)
rack (2.2.8.1)
rack-test (2.1.0)
rack (>= 1.3)
rails (6.1.7.7)
actioncable (= 6.1.7.7)
actionmailbox (= 6.1.7.7)
actionmailer (= 6.1.7.7)
actionpack (= 6.1.7.7)
actiontext (= 6.1.7.7)
actionview (= 6.1.7.7)
activejob (= 6.1.7.7)
activemodel (= 6.1.7.7)
activerecord (= 6.1.7.7)
activestorage (= 6.1.7.7)
activesupport (= 6.1.7.7)
bundler (>= 1.15.0)
railties (= 6.1.7.7)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
railties (6.1.7.7)
actionpack (= 6.1.7.7)
activesupport (= 6.1.7.7)
method_source
rake (>= 12.2)
thor (~> 1.0)
rainbow (3.1.1)
rake (13.1.0)
ransack (2.6.0)
activerecord (>= 6.0.4)
activesupport (>= 6.0.4)
i18n
regexp_parser (2.9.0)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
rexml (3.2.6)
rspec-core (3.13.0)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (6.1.1)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
rspec-core (~> 3.12)
rspec-expectations (~> 3.12)
rspec-mocks (~> 3.12)
rspec-support (~> 3.12)
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.13.1)
rspec_junit_formatter (0.6.0)
rspec-core (>= 2, < 4, != 2.12.0)
rubocop (1.60.2)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.30.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
parser (>= 3.2.1.0)
rubocop-capybara (2.20.0)
rubocop (~> 1.41)
rubocop-factory_bot (2.25.1)
rubocop (~> 1.41)
rubocop-packaging (0.5.2)
rubocop (>= 1.33, < 2.0)
rubocop-performance (1.20.2)
rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rails (2.23.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rspec (2.26.1)
rubocop (~> 1.40)
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
rubocop-rspec_rails (2.28.3)
rubocop (~> 1.40)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
ruby_parser (3.21.0)
racc (~> 1.5)
sexp_processor (~> 4.16)
sassc (2.4.0)
ffi (~> 1.9)
sexp_processor (4.17.1)
sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
sprockets-rails (3.4.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets (>= 3.0.0)
sqlite3 (1.7.2-arm64-darwin)
sqlite3 (1.7.2-x86_64-darwin)
sqlite3 (1.7.2-x86_64-linux)
thor (1.3.0)
timeout (0.4.1)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
webrick (1.8.1)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.13)
PLATFORMS
arm64-darwin-22
arm64-darwin-23
x86_64-darwin-21
x86_64-linux
DEPENDENCIES
activeadmin (~> 2.9.0)
activeadmin_quill_editor!
appraisal (~> 2.4)
bigdecimal
capybara
cuprite
fasterer
mutex_m
pry-rails
puma
rails (~> 6.1.0)
rspec-rails
rspec-retry
rspec_junit_formatter
rubocop
rubocop-capybara
rubocop-packaging
rubocop-performance
rubocop-rails
rubocop-rspec
rubocop-rspec_rails
sassc
sprockets-rails
sqlite3
BUNDLED WITH
2.3.8

Просмотреть файл

@@ -2,20 +2,17 @@
source "https://rubygems.org"
gem "rails", "~> 7.0.0"
gem "activeadmin", "~> 3.2"
gem "sqlite3"
gem "concurrent-ruby", "1.3.4"
gem "bigdecimal"
gem "csv"
gem "mutex_m"
gem "puma"
gem "sassc"
gem "sprockets-rails"
gem "capybara"
gem "cuprite"
gem "rspec_junit_formatter"
gem "rspec-rails"
gem "simplecov", require: false
gem "super_diff"
gem "rspec-retry"
gem "fasterer"
gem "rubocop"
gem "rubocop-capybara"
@@ -24,9 +21,8 @@ gem "rubocop-performance"
gem "rubocop-rails"
gem "rubocop-rspec"
gem "rubocop-rspec_rails"
gem "appraisal"
gem "pry-rails"
gem "sassc"
gem "sprockets-rails"
gem "activeadmin"
gem "rails", "~> 7.0.0"
gemspec path: "../"

354
gemfiles/rails70_activeadmin.gemfile.lock Обычный файл
Просмотреть файл

@@ -0,0 +1,354 @@
PATH
remote: ..
specs:
activeadmin_quill_editor (1.3.0)
activeadmin (>= 2.9, < 4)
GEM
remote: https://rubygems.org/
specs:
actioncable (7.0.8.1)
actionpack (= 7.0.8.1)
activesupport (= 7.0.8.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (7.0.8.1)
actionpack (= 7.0.8.1)
activejob (= 7.0.8.1)
activerecord (= 7.0.8.1)
activestorage (= 7.0.8.1)
activesupport (= 7.0.8.1)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.0.8.1)
actionpack (= 7.0.8.1)
actionview (= 7.0.8.1)
activejob (= 7.0.8.1)
activesupport (= 7.0.8.1)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.0)
actionpack (7.0.8.1)
actionview (= 7.0.8.1)
activesupport (= 7.0.8.1)
rack (~> 2.0, >= 2.2.4)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (7.0.8.1)
actionpack (= 7.0.8.1)
activerecord (= 7.0.8.1)
activestorage (= 7.0.8.1)
activesupport (= 7.0.8.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.0.8.1)
activesupport (= 7.0.8.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activeadmin (3.2.0)
arbre (~> 1.2, >= 1.2.1)
formtastic (>= 3.1)
formtastic_i18n (>= 0.4)
inherited_resources (~> 1.7)
jquery-rails (>= 4.2)
kaminari (>= 1.2.1)
railties (>= 6.1)
ransack (>= 4.0)
activejob (7.0.8.1)
activesupport (= 7.0.8.1)
globalid (>= 0.3.6)
activemodel (7.0.8.1)
activesupport (= 7.0.8.1)
activerecord (7.0.8.1)
activemodel (= 7.0.8.1)
activesupport (= 7.0.8.1)
activestorage (7.0.8.1)
actionpack (= 7.0.8.1)
activejob (= 7.0.8.1)
activerecord (= 7.0.8.1)
activesupport (= 7.0.8.1)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (7.0.8.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
appraisal (2.5.0)
bundler
rake
thor (>= 0.14.0)
arbre (1.7.0)
activesupport (>= 3.0.0)
ruby2_keywords (>= 0.0.2)
ast (2.4.2)
bigdecimal (3.1.9)
builder (3.2.4)
capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
coderay (1.1.3)
concurrent-ruby (1.2.3)
crass (1.0.6)
cuprite (0.15)
capybara (~> 3.0)
ferrum (~> 0.14.0)
date (3.3.4)
diff-lcs (1.5.1)
erubi (1.12.0)
fasterer (0.11.0)
ruby_parser (>= 3.19.1)
ferrum (0.14)
addressable (~> 2.5)
concurrent-ruby (~> 1.1)
webrick (~> 1.7)
websocket-driver (>= 0.6, < 0.8)
ffi (1.16.3)
formtastic (5.0.0)
actionpack (>= 6.0.0)
formtastic_i18n (0.7.0)
globalid (1.2.1)
activesupport (>= 6.1)
has_scope (0.8.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
inherited_resources (1.14.0)
actionpack (>= 6.0)
has_scope (>= 0.6)
railties (>= 6.0)
responders (>= 2)
jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.7.1)
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
kaminari-activerecord (= 1.2.2)
kaminari-core (= 1.2.2)
kaminari-actionview (1.2.2)
actionview
kaminari-core (= 1.2.2)
kaminari-activerecord (1.2.2)
activerecord
kaminari-core (= 1.2.2)
kaminari-core (1.2.2)
language_server-protocol (3.17.0.3)
loofah (2.22.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
mini_mime (>= 0.1.1)
net-imap
net-pop
net-smtp
marcel (1.0.2)
matrix (0.4.2)
method_source (1.0.0)
mini_mime (1.1.5)
mini_portile2 (2.8.8)
minitest (5.22.2)
mutex_m (0.3.0)
net-imap (0.4.10)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
net-smtp (0.5.1)
net-protocol
nio4r (2.7.0)
nokogiri (1.16.2)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
parallel (1.24.0)
parser (3.3.0.5)
ast (~> 2.4.1)
racc
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
public_suffix (5.0.4)
puma (6.4.2)
nio4r (~> 2.0)
racc (1.7.3)
rack (2.2.8.1)
rack-test (2.1.0)
rack (>= 1.3)
rails (7.0.8.1)
actioncable (= 7.0.8.1)
actionmailbox (= 7.0.8.1)
actionmailer (= 7.0.8.1)
actionpack (= 7.0.8.1)
actiontext (= 7.0.8.1)
actionview (= 7.0.8.1)
activejob (= 7.0.8.1)
activemodel (= 7.0.8.1)
activerecord (= 7.0.8.1)
activestorage (= 7.0.8.1)
activesupport (= 7.0.8.1)
bundler (>= 1.15.0)
railties (= 7.0.8.1)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
railties (7.0.8.1)
actionpack (= 7.0.8.1)
activesupport (= 7.0.8.1)
method_source
rake (>= 12.2)
thor (~> 1.0)
zeitwerk (~> 2.5)
rainbow (3.1.1)
rake (13.1.0)
ransack (4.1.1)
activerecord (>= 6.1.5)
activesupport (>= 6.1.5)
i18n
regexp_parser (2.9.0)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
rexml (3.2.6)
rspec-core (3.13.0)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (6.1.1)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
rspec-core (~> 3.12)
rspec-expectations (~> 3.12)
rspec-mocks (~> 3.12)
rspec-support (~> 3.12)
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.13.1)
rspec_junit_formatter (0.6.0)
rspec-core (>= 2, < 4, != 2.12.0)
rubocop (1.60.2)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.30.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
parser (>= 3.2.1.0)
rubocop-capybara (2.20.0)
rubocop (~> 1.41)
rubocop-factory_bot (2.25.1)
rubocop (~> 1.41)
rubocop-packaging (0.5.2)
rubocop (>= 1.33, < 2.0)
rubocop-performance (1.20.2)
rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rails (2.23.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rspec (2.26.1)
rubocop (~> 1.40)
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
rubocop-rspec_rails (2.28.3)
rubocop (~> 1.40)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
ruby_parser (3.21.0)
racc (~> 1.5)
sexp_processor (~> 4.16)
sassc (2.4.0)
ffi (~> 1.9)
sexp_processor (4.17.1)
sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
sprockets-rails (3.4.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets (>= 3.0.0)
sqlite3 (1.7.2)
mini_portile2 (~> 2.8.0)
thor (1.3.0)
timeout (0.4.1)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
webrick (1.8.1)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.13)
PLATFORMS
arm64-darwin-22
arm64-darwin-23
x86_64-linux
DEPENDENCIES
activeadmin
activeadmin_quill_editor!
appraisal (~> 2.4)
bigdecimal
capybara
cuprite
fasterer
mutex_m
pry-rails
puma
rails (~> 7.0.0)
rspec-rails
rspec-retry
rspec_junit_formatter
rubocop
rubocop-capybara
rubocop-packaging
rubocop-performance
rubocop-rails
rubocop-rspec
rubocop-rspec_rails
sassc
sprockets-rails
sqlite3
BUNDLED WITH
2.3.8

Просмотреть файл

@@ -2,20 +2,17 @@
source "https://rubygems.org"
gem "rails", "~> 7.1.0"
gem "activeadmin", "~> 3.2"
gem "sqlite3"
gem "concurrent-ruby", "1.3.4"
gem "bigdecimal"
gem "csv"
gem "mutex_m"
gem "puma"
gem "sassc"
gem "sprockets-rails"
gem "capybara"
gem "cuprite"
gem "rspec_junit_formatter"
gem "rspec-rails"
gem "simplecov", require: false
gem "super_diff"
gem "rspec-retry"
gem "fasterer"
gem "rubocop"
gem "rubocop-capybara"
@@ -24,9 +21,8 @@ gem "rubocop-performance"
gem "rubocop-rails"
gem "rubocop-rspec"
gem "rubocop-rspec_rails"
gem "appraisal"
gem "pry-rails"
gem "sassc"
gem "sprockets-rails"
gem "activeadmin"
gem "rails", "~> 7.1.0"
gemspec path: "../"

401
gemfiles/rails71_activeadmin.gemfile.lock Обычный файл
Просмотреть файл

@@ -0,0 +1,401 @@
PATH
remote: ..
specs:
activeadmin_quill_editor (1.3.0)
activeadmin (>= 2.9, < 4)
GEM
remote: https://rubygems.org/
specs:
actioncable (7.1.5.1)
actionpack (= 7.1.5.1)
activesupport (= 7.1.5.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
actionmailbox (7.1.5.1)
actionpack (= 7.1.5.1)
activejob (= 7.1.5.1)
activerecord (= 7.1.5.1)
activestorage (= 7.1.5.1)
activesupport (= 7.1.5.1)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.1.5.1)
actionpack (= 7.1.5.1)
actionview (= 7.1.5.1)
activejob (= 7.1.5.1)
activesupport (= 7.1.5.1)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.2)
actionpack (7.1.5.1)
actionview (= 7.1.5.1)
activesupport (= 7.1.5.1)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
actiontext (7.1.5.1)
actionpack (= 7.1.5.1)
activerecord (= 7.1.5.1)
activestorage (= 7.1.5.1)
activesupport (= 7.1.5.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.1.5.1)
activesupport (= 7.1.5.1)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
activeadmin (3.3.0)
arbre (~> 1.2, >= 1.2.1)
csv
formtastic (>= 3.1)
formtastic_i18n (>= 0.4)
inherited_resources (~> 1.7)
jquery-rails (>= 4.2)
kaminari (>= 1.2.1)
railties (>= 6.1)
ransack (>= 4.0)
activejob (7.1.5.1)
activesupport (= 7.1.5.1)
globalid (>= 0.3.6)
activemodel (7.1.5.1)
activesupport (= 7.1.5.1)
activerecord (7.1.5.1)
activemodel (= 7.1.5.1)
activesupport (= 7.1.5.1)
timeout (>= 0.4.0)
activestorage (7.1.5.1)
actionpack (= 7.1.5.1)
activejob (= 7.1.5.1)
activerecord (= 7.1.5.1)
activesupport (= 7.1.5.1)
marcel (~> 1.0)
activesupport (7.1.5.1)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
mutex_m
securerandom (>= 0.3)
tzinfo (~> 2.0)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
appraisal (2.5.0)
bundler
rake
thor (>= 0.14.0)
arbre (1.7.0)
activesupport (>= 3.0.0)
ruby2_keywords (>= 0.0.2)
ast (2.4.2)
base64 (0.2.0)
benchmark (0.4.0)
bigdecimal (3.1.9)
builder (3.3.0)
capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
coderay (1.1.3)
concurrent-ruby (1.3.5)
connection_pool (2.5.0)
crass (1.0.6)
csv (3.3.2)
cuprite (0.15.1)
capybara (~> 3.0)
ferrum (~> 0.15.0)
date (3.4.1)
diff-lcs (1.6.0)
drb (2.2.1)
erubi (1.13.1)
fasterer (0.11.0)
ruby_parser (>= 3.19.1)
ferrum (0.15)
addressable (~> 2.5)
concurrent-ruby (~> 1.1)
webrick (~> 1.7)
websocket-driver (~> 0.7)
ffi (1.17.1-arm64-darwin)
ffi (1.17.1-x86_64-linux-gnu)
formtastic (5.0.0)
actionpack (>= 6.0.0)
formtastic_i18n (0.7.0)
globalid (1.2.1)
activesupport (>= 6.1)
has_scope (0.8.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
inherited_resources (1.14.0)
actionpack (>= 6.0)
has_scope (>= 0.6)
railties (>= 6.0)
responders (>= 2)
io-console (0.8.0)
irb (1.15.1)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.10.2)
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
kaminari-activerecord (= 1.2.2)
kaminari-core (= 1.2.2)
kaminari-actionview (1.2.2)
actionview
kaminari-core (= 1.2.2)
kaminari-activerecord (1.2.2)
activerecord
kaminari-core (= 1.2.2)
kaminari-core (1.2.2)
language_server-protocol (3.17.0.4)
lint_roller (1.1.0)
logger (1.6.6)
loofah (2.24.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
mini_mime (>= 0.1.1)
net-imap
net-pop
net-smtp
marcel (1.0.4)
matrix (0.4.2)
method_source (1.1.0)
mini_mime (1.1.5)
minitest (5.25.5)
mutex_m (0.3.0)
net-imap (0.5.6)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
net-smtp (0.5.1)
net-protocol
nio4r (2.7.4)
nokogiri (1.18.4-arm64-darwin)
racc (~> 1.4)
nokogiri (1.18.4-x86_64-linux-gnu)
racc (~> 1.4)
parallel (1.26.3)
parser (3.3.7.1)
ast (~> 2.4.1)
racc
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
pry (0.15.2)
coderay (~> 1.1)
method_source (~> 1.0)
pry-rails (0.3.11)
pry (>= 0.13.0)
psych (5.2.3)
date
stringio
public_suffix (6.0.1)
puma (6.6.0)
nio4r (~> 2.0)
racc (1.8.1)
rack (3.1.12)
rack-session (2.1.0)
base64 (>= 0.1.0)
rack (>= 3.0.0)
rack-test (2.2.0)
rack (>= 1.3)
rackup (2.2.1)
rack (>= 3)
rails (7.1.5.1)
actioncable (= 7.1.5.1)
actionmailbox (= 7.1.5.1)
actionmailer (= 7.1.5.1)
actionpack (= 7.1.5.1)
actiontext (= 7.1.5.1)
actionview (= 7.1.5.1)
activejob (= 7.1.5.1)
activemodel (= 7.1.5.1)
activerecord (= 7.1.5.1)
activestorage (= 7.1.5.1)
activesupport (= 7.1.5.1)
bundler (>= 1.15.0)
railties (= 7.1.5.1)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
railties (7.1.5.1)
actionpack (= 7.1.5.1)
activesupport (= 7.1.5.1)
irb
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.2.1)
ransack (4.3.0)
activerecord (>= 6.1.5)
activesupport (>= 6.1.5)
i18n
rdoc (6.12.0)
psych (>= 4.0.0)
regexp_parser (2.10.0)
reline (0.6.0)
io-console (~> 0.5)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
rspec-core (3.13.3)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (7.1.1)
actionpack (>= 7.0)
activesupport (>= 7.0)
railties (>= 7.0)
rspec-core (~> 3.13)
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
rspec-support (~> 3.13)
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.13.2)
rspec_junit_formatter (0.6.0)
rspec-core (>= 2, < 4, != 2.12.0)
rubocop (1.74.0)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.38.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.39.0)
parser (>= 3.3.1.0)
rubocop-capybara (2.22.1)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-packaging (0.5.2)
rubocop (>= 1.33, < 2.0)
rubocop-performance (1.24.0)
lint_roller (~> 1.1)
rubocop (>= 1.72.1, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rails (2.30.3)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
rubocop (>= 1.72.1, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rspec (3.5.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec_rails (2.31.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec (~> 3.5)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
ruby_parser (3.21.1)
racc (~> 1.5)
sexp_processor (~> 4.16)
sassc (2.4.0)
ffi (~> 1.9)
securerandom (0.4.1)
sexp_processor (4.17.3)
sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
sprockets-rails (3.5.2)
actionpack (>= 6.1)
activesupport (>= 6.1)
sprockets (>= 3.0.0)
sqlite3 (2.6.0-arm64-darwin)
sqlite3 (2.6.0-x86_64-linux-gnu)
stringio (3.1.5)
thor (1.3.2)
timeout (0.4.3)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (3.1.4)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
webrick (1.9.1)
websocket-driver (0.7.7)
base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.18)
PLATFORMS
arm64-darwin-23
x86_64-linux
DEPENDENCIES
activeadmin
activeadmin_quill_editor!
appraisal (~> 2.4)
bigdecimal
capybara
cuprite
fasterer
mutex_m
pry-rails
puma
rails (~> 7.1.0)
rspec-rails
rspec-retry
rspec_junit_formatter
rubocop
rubocop-capybara
rubocop-packaging
rubocop-performance
rubocop-rails
rubocop-rspec
rubocop-rspec_rails
sassc
sprockets-rails
sqlite3
BUNDLED WITH
2.4.19

Просмотреть файл

@@ -2,20 +2,17 @@
source "https://rubygems.org"
gem "rails", "~> 7.2.0"
gem "activeadmin", "~> 3.2"
gem "sqlite3"
gem "concurrent-ruby", "1.3.4"
gem "bigdecimal"
gem "csv"
gem "mutex_m"
gem "puma"
gem "sassc"
gem "sprockets-rails"
gem "capybara"
gem "cuprite"
gem "rspec_junit_formatter"
gem "rspec-rails"
gem "simplecov", require: false
gem "super_diff"
gem "rspec-retry"
gem "fasterer"
gem "rubocop"
gem "rubocop-capybara"
@@ -24,9 +21,8 @@ gem "rubocop-performance"
gem "rubocop-rails"
gem "rubocop-rspec"
gem "rubocop-rspec_rails"
gem "appraisal"
gem "pry-rails"
gem "sassc"
gem "sprockets-rails"
gem "activeadmin"
gem "rails", "~> 7.2.0"
gemspec path: "../"

426
gemfiles/rails72_activeadmin.gemfile.lock Обычный файл
Просмотреть файл

@@ -0,0 +1,426 @@
PATH
remote: ..
specs:
activeadmin_quill_editor (1.3.0)
activeadmin (>= 2.9, < 4)
GEM
remote: https://rubygems.org/
specs:
actioncable (7.2.2.1)
actionpack (= 7.2.2.1)
activesupport (= 7.2.2.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
actionmailbox (7.2.2.1)
actionpack (= 7.2.2.1)
activejob (= 7.2.2.1)
activerecord (= 7.2.2.1)
activestorage (= 7.2.2.1)
activesupport (= 7.2.2.1)
mail (>= 2.8.0)
actionmailer (7.2.2.1)
actionpack (= 7.2.2.1)
actionview (= 7.2.2.1)
activejob (= 7.2.2.1)
activesupport (= 7.2.2.1)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
actionpack (7.2.2.1)
actionview (= 7.2.2.1)
activesupport (= 7.2.2.1)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4, < 3.2)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
useragent (~> 0.16)
actiontext (7.2.2.1)
actionpack (= 7.2.2.1)
activerecord (= 7.2.2.1)
activestorage (= 7.2.2.1)
activesupport (= 7.2.2.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.2.2.1)
activesupport (= 7.2.2.1)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
activeadmin (3.3.0)
arbre (~> 1.2, >= 1.2.1)
csv
formtastic (>= 3.1)
formtastic_i18n (>= 0.4)
inherited_resources (~> 1.7)
jquery-rails (>= 4.2)
kaminari (>= 1.2.1)
railties (>= 6.1)
ransack (>= 4.0)
activejob (7.2.2.1)
activesupport (= 7.2.2.1)
globalid (>= 0.3.6)
activemodel (7.2.2.1)
activesupport (= 7.2.2.1)
activerecord (7.2.2.1)
activemodel (= 7.2.2.1)
activesupport (= 7.2.2.1)
timeout (>= 0.4.0)
activestorage (7.2.2.1)
actionpack (= 7.2.2.1)
activejob (= 7.2.2.1)
activerecord (= 7.2.2.1)
activesupport (= 7.2.2.1)
marcel (~> 1.0)
activesupport (7.2.2.1)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
appraisal (2.5.0)
bundler
rake
thor (>= 0.14.0)
arbre (1.7.0)
activesupport (>= 3.0.0)
ruby2_keywords (>= 0.0.2)
ast (2.4.2)
base64 (0.2.0)
benchmark (0.4.0)
bigdecimal (3.1.9)
builder (3.3.0)
capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
coderay (1.1.3)
concurrent-ruby (1.3.5)
connection_pool (2.5.0)
crass (1.0.6)
csv (3.3.2)
cuprite (0.15.1)
capybara (~> 3.0)
ferrum (~> 0.15.0)
date (3.4.1)
diff-lcs (1.6.0)
drb (2.2.1)
erubi (1.13.1)
fasterer (0.11.0)
ruby_parser (>= 3.19.1)
ferrum (0.15)
addressable (~> 2.5)
concurrent-ruby (~> 1.1)
webrick (~> 1.7)
websocket-driver (~> 0.7)
ffi (1.17.1-aarch64-linux-gnu)
ffi (1.17.1-aarch64-linux-musl)
ffi (1.17.1-arm-linux-gnu)
ffi (1.17.1-arm-linux-musl)
ffi (1.17.1-arm64-darwin)
ffi (1.17.1-x86_64-darwin)
ffi (1.17.1-x86_64-linux-gnu)
ffi (1.17.1-x86_64-linux-musl)
formtastic (5.0.0)
actionpack (>= 6.0.0)
formtastic_i18n (0.7.0)
globalid (1.2.1)
activesupport (>= 6.1)
has_scope (0.8.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
inherited_resources (1.14.0)
actionpack (>= 6.0)
has_scope (>= 0.6)
railties (>= 6.0)
responders (>= 2)
io-console (0.8.0)
irb (1.15.1)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.10.2)
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
kaminari-activerecord (= 1.2.2)
kaminari-core (= 1.2.2)
kaminari-actionview (1.2.2)
actionview
kaminari-core (= 1.2.2)
kaminari-activerecord (1.2.2)
activerecord
kaminari-core (= 1.2.2)
kaminari-core (1.2.2)
language_server-protocol (3.17.0.4)
lint_roller (1.1.0)
logger (1.6.6)
loofah (2.24.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
mini_mime (>= 0.1.1)
net-imap
net-pop
net-smtp
marcel (1.0.4)
matrix (0.4.2)
method_source (1.1.0)
mini_mime (1.1.5)
minitest (5.25.5)
mutex_m (0.3.0)
net-imap (0.5.6)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
net-smtp (0.5.1)
net-protocol
nio4r (2.7.4)
nokogiri (1.18.4-aarch64-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.4-aarch64-linux-musl)
racc (~> 1.4)
nokogiri (1.18.4-arm-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.4-arm-linux-musl)
racc (~> 1.4)
nokogiri (1.18.4-arm64-darwin)
racc (~> 1.4)
nokogiri (1.18.4-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.18.4-x86_64-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.4-x86_64-linux-musl)
racc (~> 1.4)
parallel (1.26.3)
parser (3.3.7.1)
ast (~> 2.4.1)
racc
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
pry (0.15.2)
coderay (~> 1.1)
method_source (~> 1.0)
pry-rails (0.3.11)
pry (>= 0.13.0)
psych (5.2.3)
date
stringio
public_suffix (6.0.1)
puma (6.6.0)
nio4r (~> 2.0)
racc (1.8.1)
rack (3.1.12)
rack-session (2.1.0)
base64 (>= 0.1.0)
rack (>= 3.0.0)
rack-test (2.2.0)
rack (>= 1.3)
rackup (2.2.1)
rack (>= 3)
rails (7.2.2.1)
actioncable (= 7.2.2.1)
actionmailbox (= 7.2.2.1)
actionmailer (= 7.2.2.1)
actionpack (= 7.2.2.1)
actiontext (= 7.2.2.1)
actionview (= 7.2.2.1)
activejob (= 7.2.2.1)
activemodel (= 7.2.2.1)
activerecord (= 7.2.2.1)
activestorage (= 7.2.2.1)
activesupport (= 7.2.2.1)
bundler (>= 1.15.0)
railties (= 7.2.2.1)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
railties (7.2.2.1)
actionpack (= 7.2.2.1)
activesupport (= 7.2.2.1)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.2.1)
ransack (4.3.0)
activerecord (>= 6.1.5)
activesupport (>= 6.1.5)
i18n
rdoc (6.12.0)
psych (>= 4.0.0)
regexp_parser (2.10.0)
reline (0.6.0)
io-console (~> 0.5)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
rspec-core (3.13.3)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (7.1.1)
actionpack (>= 7.0)
activesupport (>= 7.0)
railties (>= 7.0)
rspec-core (~> 3.13)
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
rspec-support (~> 3.13)
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.13.2)
rspec_junit_formatter (0.6.0)
rspec-core (>= 2, < 4, != 2.12.0)
rubocop (1.74.0)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.38.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.39.0)
parser (>= 3.3.1.0)
rubocop-capybara (2.22.1)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-packaging (0.5.2)
rubocop (>= 1.33, < 2.0)
rubocop-performance (1.24.0)
lint_roller (~> 1.1)
rubocop (>= 1.72.1, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rails (2.30.3)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
rubocop (>= 1.72.1, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rspec (3.5.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec_rails (2.31.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec (~> 3.5)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
ruby_parser (3.21.1)
racc (~> 1.5)
sexp_processor (~> 4.16)
sassc (2.4.0)
ffi (~> 1.9)
securerandom (0.4.1)
sexp_processor (4.17.3)
sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
sprockets-rails (3.5.2)
actionpack (>= 6.1)
activesupport (>= 6.1)
sprockets (>= 3.0.0)
sqlite3 (2.6.0-aarch64-linux-gnu)
sqlite3 (2.6.0-aarch64-linux-musl)
sqlite3 (2.6.0-arm-linux-gnu)
sqlite3 (2.6.0-arm-linux-musl)
sqlite3 (2.6.0-arm64-darwin)
sqlite3 (2.6.0-x86_64-darwin)
sqlite3 (2.6.0-x86_64-linux-gnu)
sqlite3 (2.6.0-x86_64-linux-musl)
stringio (3.1.5)
thor (1.3.2)
timeout (0.4.3)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (3.1.4)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
useragent (0.16.11)
webrick (1.9.1)
websocket-driver (0.7.7)
base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.18)
PLATFORMS
aarch64-linux-gnu
aarch64-linux-musl
arm-linux-gnu
arm-linux-musl
arm64-darwin
x86_64-darwin
x86_64-linux-gnu
x86_64-linux-musl
DEPENDENCIES
activeadmin
activeadmin_quill_editor!
appraisal (~> 2.4)
bigdecimal
capybara
cuprite
fasterer
mutex_m
pry-rails
puma
rails (~> 7.2.0)
rspec-rails
rspec-retry
rspec_junit_formatter
rubocop
rubocop-capybara
rubocop-packaging
rubocop-performance
rubocop-rails
rubocop-rspec
rubocop-rspec_rails
sassc
sprockets-rails
sqlite3
BUNDLED WITH
2.6.6

Просмотреть файл

@@ -2,20 +2,17 @@
source "https://rubygems.org"
gem "rails", "~> 7.0.0"
gem "activeadmin", "~> 2.14"
gem "sqlite3"
gem "concurrent-ruby", "1.3.4"
gem "bigdecimal"
gem "csv"
gem "mutex_m"
gem "puma"
gem "sassc"
gem "sprockets-rails"
gem "capybara"
gem "cuprite"
gem "rspec_junit_formatter"
gem "rspec-rails"
gem "simplecov", require: false
gem "super_diff"
gem "rspec-retry"
gem "fasterer"
gem "rubocop"
gem "rubocop-capybara"
@@ -24,9 +21,8 @@ gem "rubocop-performance"
gem "rubocop-rails"
gem "rubocop-rspec"
gem "rubocop-rspec_rails"
gem "appraisal"
gem "pry-rails"
gem "sassc"
gem "sprockets-rails"
gem "activeadmin"
gem "rails", "~> 8.0.0"
gemspec path: "../"

427
gemfiles/rails80_activeadmin.gemfile.lock Обычный файл
Просмотреть файл

@@ -0,0 +1,427 @@
PATH
remote: ..
specs:
activeadmin_quill_editor (1.3.0)
activeadmin (>= 2.9, < 4)
GEM
remote: https://rubygems.org/
specs:
actioncable (8.0.2)
actionpack (= 8.0.2)
activesupport (= 8.0.2)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
actionmailbox (8.0.2)
actionpack (= 8.0.2)
activejob (= 8.0.2)
activerecord (= 8.0.2)
activestorage (= 8.0.2)
activesupport (= 8.0.2)
mail (>= 2.8.0)
actionmailer (8.0.2)
actionpack (= 8.0.2)
actionview (= 8.0.2)
activejob (= 8.0.2)
activesupport (= 8.0.2)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
actionpack (8.0.2)
actionview (= 8.0.2)
activesupport (= 8.0.2)
nokogiri (>= 1.8.5)
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
useragent (~> 0.16)
actiontext (8.0.2)
actionpack (= 8.0.2)
activerecord (= 8.0.2)
activestorage (= 8.0.2)
activesupport (= 8.0.2)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (8.0.2)
activesupport (= 8.0.2)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
activeadmin (3.3.0)
arbre (~> 1.2, >= 1.2.1)
csv
formtastic (>= 3.1)
formtastic_i18n (>= 0.4)
inherited_resources (~> 1.7)
jquery-rails (>= 4.2)
kaminari (>= 1.2.1)
railties (>= 6.1)
ransack (>= 4.0)
activejob (8.0.2)
activesupport (= 8.0.2)
globalid (>= 0.3.6)
activemodel (8.0.2)
activesupport (= 8.0.2)
activerecord (8.0.2)
activemodel (= 8.0.2)
activesupport (= 8.0.2)
timeout (>= 0.4.0)
activestorage (8.0.2)
actionpack (= 8.0.2)
activejob (= 8.0.2)
activerecord (= 8.0.2)
activesupport (= 8.0.2)
marcel (~> 1.0)
activesupport (8.0.2)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
appraisal (2.5.0)
bundler
rake
thor (>= 0.14.0)
arbre (1.7.0)
activesupport (>= 3.0.0)
ruby2_keywords (>= 0.0.2)
ast (2.4.2)
base64 (0.2.0)
benchmark (0.4.0)
bigdecimal (3.1.9)
builder (3.3.0)
capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
coderay (1.1.3)
concurrent-ruby (1.3.5)
connection_pool (2.5.0)
crass (1.0.6)
csv (3.3.2)
cuprite (0.15.1)
capybara (~> 3.0)
ferrum (~> 0.15.0)
date (3.4.1)
diff-lcs (1.6.0)
drb (2.2.1)
erubi (1.13.1)
fasterer (0.11.0)
ruby_parser (>= 3.19.1)
ferrum (0.15)
addressable (~> 2.5)
concurrent-ruby (~> 1.1)
webrick (~> 1.7)
websocket-driver (~> 0.7)
ffi (1.17.1-aarch64-linux-gnu)
ffi (1.17.1-aarch64-linux-musl)
ffi (1.17.1-arm-linux-gnu)
ffi (1.17.1-arm-linux-musl)
ffi (1.17.1-arm64-darwin)
ffi (1.17.1-x86_64-darwin)
ffi (1.17.1-x86_64-linux-gnu)
ffi (1.17.1-x86_64-linux-musl)
formtastic (5.0.0)
actionpack (>= 6.0.0)
formtastic_i18n (0.7.0)
globalid (1.2.1)
activesupport (>= 6.1)
has_scope (0.8.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
inherited_resources (1.14.0)
actionpack (>= 6.0)
has_scope (>= 0.6)
railties (>= 6.0)
responders (>= 2)
io-console (0.8.0)
irb (1.15.1)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.10.2)
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
kaminari-activerecord (= 1.2.2)
kaminari-core (= 1.2.2)
kaminari-actionview (1.2.2)
actionview
kaminari-core (= 1.2.2)
kaminari-activerecord (1.2.2)
activerecord
kaminari-core (= 1.2.2)
kaminari-core (1.2.2)
language_server-protocol (3.17.0.4)
lint_roller (1.1.0)
logger (1.6.6)
loofah (2.24.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
mini_mime (>= 0.1.1)
net-imap
net-pop
net-smtp
marcel (1.0.4)
matrix (0.4.2)
method_source (1.1.0)
mini_mime (1.1.5)
minitest (5.25.5)
mutex_m (0.3.0)
net-imap (0.5.6)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
net-smtp (0.5.1)
net-protocol
nio4r (2.7.4)
nokogiri (1.18.4-aarch64-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.4-aarch64-linux-musl)
racc (~> 1.4)
nokogiri (1.18.4-arm-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.4-arm-linux-musl)
racc (~> 1.4)
nokogiri (1.18.4-arm64-darwin)
racc (~> 1.4)
nokogiri (1.18.4-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.18.4-x86_64-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.4-x86_64-linux-musl)
racc (~> 1.4)
parallel (1.26.3)
parser (3.3.7.1)
ast (~> 2.4.1)
racc
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
pry (0.15.2)
coderay (~> 1.1)
method_source (~> 1.0)
pry-rails (0.3.11)
pry (>= 0.13.0)
psych (5.2.3)
date
stringio
public_suffix (6.0.1)
puma (6.6.0)
nio4r (~> 2.0)
racc (1.8.1)
rack (3.1.12)
rack-session (2.1.0)
base64 (>= 0.1.0)
rack (>= 3.0.0)
rack-test (2.2.0)
rack (>= 1.3)
rackup (2.2.1)
rack (>= 3)
rails (8.0.2)
actioncable (= 8.0.2)
actionmailbox (= 8.0.2)
actionmailer (= 8.0.2)
actionpack (= 8.0.2)
actiontext (= 8.0.2)
actionview (= 8.0.2)
activejob (= 8.0.2)
activemodel (= 8.0.2)
activerecord (= 8.0.2)
activestorage (= 8.0.2)
activesupport (= 8.0.2)
bundler (>= 1.15.0)
railties (= 8.0.2)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
railties (8.0.2)
actionpack (= 8.0.2)
activesupport (= 8.0.2)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.2.1)
ransack (4.3.0)
activerecord (>= 6.1.5)
activesupport (>= 6.1.5)
i18n
rdoc (6.12.0)
psych (>= 4.0.0)
regexp_parser (2.10.0)
reline (0.6.0)
io-console (~> 0.5)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
rspec-core (3.13.3)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (7.1.1)
actionpack (>= 7.0)
activesupport (>= 7.0)
railties (>= 7.0)
rspec-core (~> 3.13)
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
rspec-support (~> 3.13)
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.13.2)
rspec_junit_formatter (0.6.0)
rspec-core (>= 2, < 4, != 2.12.0)
rubocop (1.74.0)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.38.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.39.0)
parser (>= 3.3.1.0)
rubocop-capybara (2.22.1)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-packaging (0.5.2)
rubocop (>= 1.33, < 2.0)
rubocop-performance (1.24.0)
lint_roller (~> 1.1)
rubocop (>= 1.72.1, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rails (2.30.3)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
rubocop (>= 1.72.1, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rspec (3.5.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec_rails (2.31.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec (~> 3.5)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
ruby_parser (3.21.1)
racc (~> 1.5)
sexp_processor (~> 4.16)
sassc (2.4.0)
ffi (~> 1.9)
securerandom (0.4.1)
sexp_processor (4.17.3)
sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
sprockets-rails (3.5.2)
actionpack (>= 6.1)
activesupport (>= 6.1)
sprockets (>= 3.0.0)
sqlite3 (2.6.0-aarch64-linux-gnu)
sqlite3 (2.6.0-aarch64-linux-musl)
sqlite3 (2.6.0-arm-linux-gnu)
sqlite3 (2.6.0-arm-linux-musl)
sqlite3 (2.6.0-arm64-darwin)
sqlite3 (2.6.0-x86_64-darwin)
sqlite3 (2.6.0-x86_64-linux-gnu)
sqlite3 (2.6.0-x86_64-linux-musl)
stringio (3.1.5)
thor (1.3.2)
timeout (0.4.3)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (3.1.4)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
uri (1.0.3)
useragent (0.16.11)
webrick (1.9.1)
websocket-driver (0.7.7)
base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.7.2)
PLATFORMS
aarch64-linux-gnu
aarch64-linux-musl
arm-linux-gnu
arm-linux-musl
arm64-darwin
x86_64-darwin
x86_64-linux-gnu
x86_64-linux-musl
DEPENDENCIES
activeadmin
activeadmin_quill_editor!
appraisal (~> 2.4)
bigdecimal
capybara
cuprite
fasterer
mutex_m
pry-rails
puma
rails (~> 8.0.0)
rspec-rails
rspec-retry
rspec_junit_formatter
rubocop
rubocop-capybara
rubocop-packaging
rubocop-performance
rubocop-rails
rubocop-rspec
rubocop-rspec_rails
sassc
sprockets-rails
sqlite3
BUNDLED WITH
2.6.6

Просмотреть файл

@@ -1,32 +0,0 @@
# This file was generated by Appraisal
source "https://rubygems.org"
gem "rails", "~> 7.2.0"
gem "activeadmin", "4.0.0.beta16"
gem "sqlite3"
gem "concurrent-ruby", "1.3.4"
gem "bigdecimal"
gem "csv"
gem "mutex_m"
gem "puma"
gem "importmap-rails"
gem "propshaft"
gem "capybara"
gem "cuprite"
gem "rspec_junit_formatter"
gem "rspec-rails"
gem "simplecov", require: false
gem "super_diff"
gem "fasterer"
gem "rubocop"
gem "rubocop-capybara"
gem "rubocop-packaging"
gem "rubocop-performance"
gem "rubocop-rails"
gem "rubocop-rspec"
gem "rubocop-rspec_rails"
gem "appraisal"
gem "pry-rails"
gemspec path: "../"

Просмотреть файл

@@ -1,32 +0,0 @@
# This file was generated by Appraisal
source "https://rubygems.org"
gem "rails", "~> 8.0.0"
gem "activeadmin", "4.0.0.beta16"
gem "sqlite3"
gem "concurrent-ruby", "1.3.4"
gem "bigdecimal"
gem "csv"
gem "mutex_m"
gem "puma"
gem "importmap-rails"
gem "propshaft"
gem "capybara"
gem "cuprite"
gem "rspec_junit_formatter"
gem "rspec-rails"
gem "simplecov", require: false
gem "super_diff"
gem "fasterer"
gem "rubocop"
gem "rubocop-capybara"
gem "rubocop-packaging"
gem "rubocop-performance"
gem "rubocop-rails"
gem "rubocop-rspec"
gem "rubocop-rspec_rails"
gem "appraisal"
gem "pry-rails"
gemspec path: "../"

Просмотреть файл

@@ -1,4 +1,3 @@
# frozen_string_literal: true
require 'activeadmin/quill_editor/engine'
require 'formtastic/inputs/quill_editor_input'

Просмотреть файл

@@ -6,30 +6,6 @@ module ActiveAdmin
module QuillEditor
class Engine < ::Rails::Engine
engine_name 'activeadmin_quill_editor'
# Propshaft automatically includes vendor/assets and app/assets paths
# No need for explicit asset path configuration with Propshaft
initializer 'activeadmin_quill_editor.assets' do |app|
# For Propshaft (Rails 8 default)
if defined?(Propshaft)
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
]
end
end
initializer 'activeadmin_quill_editor.formtastic' do
ActiveSupport.on_load :active_admin do
require 'formtastic/inputs/quill_editor_input'
end
end
end
end
end

Просмотреть файл

@@ -2,7 +2,7 @@
module ActiveAdmin
module QuillEditor
VERSION = '2.0.0'
QUILL_VERSION = '2.0.3'
VERSION = '1.3.0'
QUILL_VERSION = '1.3.7'
end
end

Просмотреть файл

@@ -1,6 +1,6 @@
{
"name": "activeadmin_quill_editor",
"version": "2.0.0",
"version": "1.3.0",
"description": "Quill Editor for ActiveAdmin",
"author": "Mattia Roccoberton <mat@blocknot.es>",
"license": "MIT",

Просмотреть файл

@@ -33,7 +33,7 @@ ActiveAdmin.register Author do
row :profile
row :posts
end
active_admin_comments_for(resource) if active_admin_config.comments?
active_admin_comments
end
form do |f|

Просмотреть файл

@@ -3,12 +3,6 @@
ActiveAdmin.register Post do
permit_params :author_id, :title, :summary, :description, :category, :dt, :position, :published, tag_ids: []
member_action :upload, method: [:post] do
result = { success: resource.images.attach(params[:file_upload]) }
result[:url] = url_for(resource.images.last) if result[:success]
render json: result
end
index do
selectable_column
id_column
@@ -41,7 +35,7 @@ ActiveAdmin.register Post do
nil
end
end
active_admin_comments_for(resource) if active_admin_config.comments?
active_admin_comments
end
form do |f|
@@ -50,12 +44,7 @@ ActiveAdmin.register Post do
f.input :author
f.input :title
f.input :summary, as: :quill_editor, input_html: { data: { options: { modules: { toolbar: toolbar } } } }
if object.new_record?
f.input :description, as: :quill_editor # using default options
else
plugin_opts = { image_uploader: { server_url: upload_admin_post_path(object.id), field_name: 'file_upload' } }
f.input :description, as: :quill_editor, input_html: { data: { plugins: plugin_opts } }
end
f.input :description, as: :quill_editor, input_html: { data: { options: { modules: { toolbar: toolbar } } } }
f.input :category
f.input :dt
f.input :position

Просмотреть файл

@@ -1,5 +1,4 @@
# frozen_string_literal: true
ActiveAdmin.register Tag do
permit_params :name
end

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@@ -1,7 +1,3 @@
//= link_tree ../images
//= link_directory ../javascripts .js
//= link active_admin.css
//= link active_admin.js
//= link activeadmin_quill_editor.js
//= link application.css
//= link_directory ../stylesheets .css
// OFF link active_storage_db_manifest.js

Просмотреть файл

@@ -2,5 +2,3 @@
//= require activeadmin/quill_editor/quill
//= require activeadmin/quill_editor_input
//= require activeadmin/quill.imageUploader.min

Просмотреть файл

@@ -1 +0,0 @@
../../../../../vendor/assets/javascripts/activeadmin_quill_editor.js

Просмотреть файл

@@ -1,2 +0,0 @@
//= require_tree ../builds
//= require activeadmin_quill_editor

Просмотреть файл

@@ -1,73 +0,0 @@
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
/* Import Quill styles */
@import "../../../node_modules/quill/dist/quill.snow.css";
@import "../../../node_modules/quill/dist/quill.bubble.css";
/* Custom Quill integration styles for ActiveAdmin */
@layer components {
.quill-editor {
@apply border border-gray-300 rounded-md;
}
.ql-toolbar {
@apply border-b-0 rounded-t-md;
}
.ql-container {
@apply rounded-b-md;
}
.ql-editor {
@apply min-h-[200px];
}
/* Dark mode support */
.dark .quill-editor {
@apply border-gray-600;
}
.dark .ql-toolbar {
@apply bg-gray-800 border-gray-600;
}
.dark .ql-container {
@apply bg-gray-900 border-gray-600;
}
.dark .ql-editor {
@apply text-gray-100;
}
/* Fix toolbar button styles */
.ql-toolbar button:hover {
@apply bg-gray-100 dark:bg-gray-700;
}
/* Ensure icons are visible in dark mode */
.dark .ql-toolbar button svg {
@apply text-gray-300;
}
.dark .ql-toolbar button:hover svg {
@apply text-white;
}
.dark .ql-toolbar .ql-stroke {
stroke: #9ca3af !important;
}
.dark .ql-toolbar .ql-fill {
fill: #9ca3af !important;
}
.dark .ql-toolbar button:hover .ql-stroke {
stroke: white !important;
}
.dark .ql-toolbar button:hover .ql-fill {
fill: white !important;
}
}

Просмотреть файл

@@ -14,8 +14,6 @@
@import 'activeadmin/quill_editor/quill.snow';
@import 'activeadmin/quill_editor_input';
@import 'activeadmin/quill.imageUploader.min';
// Overriding any non-variable SASS must be done after the fact.
// For example, to change the default status-tag color:
//

Просмотреть файл

@@ -1,26 +0,0 @@
// Import ActiveAdmin - this already includes all features and Rails UJS
// DO NOT import Rails separately as it's already included and started in ActiveAdmin
import '@activeadmin/activeadmin';
// Import Quill from NPM and make it globally available
import Quill from 'quill';
window.Quill = Quill;
// Import the image uploader plugin if available (optional)
try {
const ImageUploader = require('quill-image-uploader');
window.ImageUploader = ImageUploader.default || ImageUploader;
} catch(e) {
// Image uploader is optional (silent failure)
}
// Import the Quill Editor initialization module
import QuillEditorModule from 'activeadmin_quill_editor';
// Now that Quill is available, initialize the editors
// This ensures proper initialization order without setTimeout hacks
if (window.QuillEditor && window.QuillEditor.init) {
window.QuillEditor.init();
} else if (QuillEditorModule && QuillEditorModule.init) {
QuillEditorModule.init();
}

Просмотреть файл

@@ -1,6 +1,8 @@
# frozen_string_literal: true
class Post < ApplicationRecord
# enum state: %i[available unavailable arriving]
belongs_to :author, inverse_of: :posts, autosave: true
has_one :author_profile, through: :author, source: :profile
@@ -26,12 +28,12 @@ class Post < ApplicationRecord
end
class << self
def ransackable_associations(_auth_object = nil)
%w[author author_profile post_tags tags images_attachments images_blobs]
def ransackable_attributes(auth_object = nil)
%w[author_id category created_at description dt id position published summary title updated_at]
end
def ransackable_attributes(_auth_object = nil)
%w[author_id category created_at description dt id position published title summary updated_at]
def ransackable_associations(auth_object = nil)
%w[author author_profile images_attachments images_blobs post_tags tags]
end
end
end

Просмотреть файл

@@ -3,12 +3,14 @@
class Profile < ApplicationRecord
belongs_to :author, inverse_of: :profile, touch: true
def to_s
description
end
# has_rich_text :description
# def to_s
# description
# end
class << self
def ransackable_associations(_auth_object = nil)
def ransackable_associations(auth_object = nil)
%w[author]
end

Просмотреть файл

@@ -6,7 +6,6 @@
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all' %>
<%= javascript_include_tag 'application', 'data-turbo-track': 'reload', defer: true %>
</head>
<body>

Просмотреть файл

@@ -1,191 +0,0 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');
const root = __dirname;
const inputPath = path.join(root, 'app/css/active_admin_source.css');
const vendorCssPath = path.join(root, 'node_modules/quill/dist/quill.snow.css');
const vendorBubbleCssPath = path.join(root, 'node_modules/quill/dist/quill.bubble.css');
const tmpPath = path.join(root, 'app/css/__aa_tmp.css');
const outPath = path.join(root, 'app/assets/builds/active_admin.css');
function build() {
// Read source file
let srcContent = '';
if (fs.existsSync(inputPath)) {
srcContent = fs.readFileSync(inputPath, 'utf8');
} else {
// Create default source if it doesn't exist
srcContent = `@tailwind base;
@tailwind components;
@tailwind utilities;`;
}
// Extract tailwind directives and body content
const lines = srcContent.split(/\r?\n/);
const tailwindLines = lines.filter(line => line.includes('@tailwind'));
const bodyLines = lines.filter(line =>
!line.includes('@tailwind') &&
!line.includes('quill/dist/quill')
);
const tailwindDirectives = tailwindLines.join('\n') || '@tailwind base;\n@tailwind components;\n@tailwind utilities;';
// Read Quill vendor CSS
let vendorCss = '';
if (fs.existsSync(vendorCssPath)) {
vendorCss += `\n/* Begin Quill Snow theme CSS */\n`;
vendorCss += fs.readFileSync(vendorCssPath, 'utf8');
vendorCss += `\n/* End Quill Snow theme CSS */\n`;
} else {
console.warn('Warning: Quill Snow CSS not found at', vendorCssPath);
}
if (fs.existsSync(vendorBubbleCssPath)) {
vendorCss += `\n/* Begin Quill Bubble theme CSS */\n`;
vendorCss += fs.readFileSync(vendorBubbleCssPath, 'utf8');
vendorCss += `\n/* End Quill Bubble theme CSS */\n`;
} else {
console.warn('Warning: Quill Bubble CSS not found at', vendorBubbleCssPath);
}
const body = bodyLines.join('\n');
// Add custom Quill styles for ActiveAdmin integration
const customStyles = `
/* Custom Quill integration styles */
.quill-editor {
@apply border border-gray-300 rounded-md;
}
.ql-toolbar {
@apply border-b-0 rounded-t-md;
}
.ql-container {
@apply rounded-b-md;
}
.ql-editor {
@apply min-h-[200px];
}
/* Dark mode support */
.dark .quill-editor {
@apply border-gray-600;
}
.dark .ql-toolbar {
@apply bg-gray-800 border-gray-600;
}
.dark .ql-container {
@apply bg-gray-900 border-gray-600;
}
.dark .ql-editor {
@apply text-gray-100;
}
/* Fix toolbar button styles */
.ql-toolbar button:hover {
@apply bg-gray-100 dark:bg-gray-700;
}
/* Ensure icons are visible in dark mode */
.dark .ql-toolbar button svg {
@apply text-gray-300;
}
.dark .ql-toolbar button:hover svg {
@apply text-white;
}
.dark .ql-toolbar .ql-stroke {
stroke: #9ca3af !important;
}
.dark .ql-toolbar .ql-fill {
fill: #9ca3af !important;
}
.dark .ql-toolbar button:hover .ql-stroke {
stroke: white !important;
}
.dark .ql-toolbar button:hover .ql-fill {
fill: white !important;
}`;
// Combine all CSS - Tailwind directives, vendor CSS, custom styles, then body
const tmpCss = `${tailwindDirectives}\n${vendorCss}\n${customStyles}\n${body}`;
// Create directories if they don't exist
const cssDir = path.dirname(tmpPath);
if (!fs.existsSync(cssDir)) {
fs.mkdirSync(cssDir, { recursive: true });
}
const buildDir = path.dirname(outPath);
if (!fs.existsSync(buildDir)) {
fs.mkdirSync(buildDir, { recursive: true });
}
fs.writeFileSync(tmpPath, tmpCss, 'utf8');
// Run tailwindcss build
const res = spawnSync('npx', [
'tailwindcss',
'-c', path.join(root, 'tailwind-active_admin.config.js'),
'-i', tmpPath,
'-o', outPath,
'--minify'
], { stdio: 'inherit', cwd: root });
if (res.status !== 0) {
console.error('Tailwind build failed');
process.exit(res.status || 1);
}
// Clean up temp file
fs.unlinkSync(tmpPath);
console.log(`ActiveAdmin CSS built successfully: ${outPath}`);
const stats = fs.statSync(outPath);
console.log(`File size: ${(stats.size / 1024).toFixed(2)} KB`);
}
// Support watch mode
if (process.argv.includes('--watch')) {
console.log('Watching for changes...');
// Initial build
build();
// Watch for changes
const watchPaths = [
inputPath,
path.join(root, 'tailwind-active_admin.config.js'),
path.join(root, 'app/admin'),
path.join(root, 'app/views')
];
const chokidar = require('chokidar');
const watcher = chokidar.watch(watchPaths, {
ignored: /node_modules|\.git|__aa_tmp\.css/,
persistent: true
});
watcher.on('change', () => {
console.log('Changes detected, rebuilding...');
try {
build();
} catch (err) {
console.error('Build error:', err);
}
});
} else {
build();
}

Просмотреть файл

@@ -1,23 +1,26 @@
require_relative 'boot'
require 'rails/all'
require 'sprockets/railtie'
Bundler.require(*Rails.groups)
module Dummy
class Application < Rails::Application
config.load_defaults Rails::VERSION::STRING.to_f
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.0 if Rails::VERSION::MAJOR == 6
config.active_support.deprecation = :raise
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
if Gem::Version.new(Rails.version) < Gem::Version.new('7.1')
config.active_record.legacy_connection_handling = false
end
###
if Gem::Version.new(Rails.version) > Gem::Version.new('7.0')
config.before_configuration do
ActiveSupport::Cache.format_version = 7.0
end
config.active_record.legacy_connection_handling = false if Gem::Version.new(Rails.version) < Gem::Version.new('7.1')
config.before_configuration do
ActiveSupport::Cache.format_version = 7.0 if Gem::Version.new(Rails.version) > Gem::Version.new('7.0')
end
end
end

Просмотреть файл

@@ -6,7 +6,7 @@ default: &default
development:
<<: *default
database: db/development.sqlite3
schema_dump: schema-dev.rb
schema_dump: schema_development.rb
test:
<<: *default

Просмотреть файл

@@ -216,9 +216,6 @@ ActiveAdmin.setup do |config|
# To load a javascript file:
# config.register_javascript 'my_javascript.js'
# ActiveAdmin 4 with Propshaft loads assets via the application layout
# and the manifest.js file, not via register_stylesheet/register_javascript
# == CSV options
#
# Set the CSV builder separator

Просмотреть файл

@@ -1,9 +1,7 @@
Rails.application.reloader.to_prepare do
ActiveSupport::Reloader.to_prepare do
ActiveStorage::Attachment.class_eval do
class << self
def ransackable_attributes(auth_object = nil)
%w[blob_id created_at id name record_id record_type]
end
def self.ransackable_attributes(auth_object = nil)
%w[blob_id created_at id name record_id record_type]
end
end
end

Просмотреть файл

@@ -0,0 +1,27 @@
# This migration comes from active_storage (originally 20170806125915)
class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
def change
create_table :active_storage_blobs do |t|
t.string :key, null: false
t.string :filename, null: false
t.string :content_type
t.text :metadata
t.bigint :byte_size, null: false
t.string :checksum, null: false
t.datetime :created_at, null: false
t.index [ :key ], unique: true
end
create_table :active_storage_attachments do |t|
t.string :name, null: false
t.references :record, null: false, polymorphic: true, index: false
t.references :blob, null: false
t.datetime :created_at, null: false
t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
end
end

Просмотреть файл

@@ -1,5 +1,3 @@
# frozen_string_literal: true
class CreateActiveAdminComments < ActiveRecord::Migration[6.0]
def self.up
create_table :active_admin_comments do |t|

Просмотреть файл

@@ -1,59 +0,0 @@
# frozen_string_literal: true
# This migration comes from active_storage (originally 20170806125915)
class CreateActiveStorageTables < ActiveRecord::Migration[6.0]
def change
# Use Active Record's configured type for primary and foreign keys
primary_key_type, foreign_key_type = primary_and_foreign_key_types
create_table :active_storage_blobs, id: primary_key_type do |t|
t.string :key, null: false
t.string :filename, null: false
t.string :content_type
t.text :metadata
t.string :service_name, null: false
t.bigint :byte_size, null: false
t.string :checksum
if connection.supports_datetime_with_precision?
t.datetime :created_at, precision: 6, null: false
else
t.datetime :created_at, null: false
end
t.index [ :key ], unique: true
end
create_table :active_storage_attachments, id: primary_key_type do |t|
t.string :name, null: false
t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type
t.references :blob, null: false, type: foreign_key_type
if connection.supports_datetime_with_precision?
t.datetime :created_at, precision: 6, null: false
else
t.datetime :created_at, null: false
end
t.index [ :record_type, :record_id, :name, :blob_id ], name: :index_active_storage_attachments_uniqueness, unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
create_table :active_storage_variant_records, id: primary_key_type do |t|
t.belongs_to :blob, null: false, index: false, type: foreign_key_type
t.string :variation_digest, null: false
t.index [ :blob_id, :variation_digest ], name: :index_active_storage_variant_records_uniqueness, unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
end
private
def primary_and_foreign_key_types
config = Rails.configuration.generators
setting = config.options[config.orm][:primary_key_type]
primary_key_type = setting || :primary_key
foreign_key_type = setting || :bigint
[ primary_key_type, foreign_key_type ]
end
end

Просмотреть файл

@@ -1,6 +1,6 @@
# frozen_string_literal: true
class CreateAuthors < ActiveRecord::Migration[6.0]
class CreateAuthors < ActiveRecord::Migration[5.2]
def change
create_table :authors do |t|
t.string :name

Просмотреть файл

@@ -1,6 +1,6 @@
# frozen_string_literal: true
class CreateProfiles < ActiveRecord::Migration[6.0]
class CreateProfiles < ActiveRecord::Migration[5.2]
def change
create_table :profiles do |t|
t.text :description

Просмотреть файл

@@ -1,6 +1,6 @@
# frozen_string_literal: true
class CreateTags < ActiveRecord::Migration[6.0]
class CreateTags < ActiveRecord::Migration[5.2]
def change
create_table :tags do |t|
t.string :name

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше