scrapbook 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -0
- data/app/assets/builds/scrapbook/application.css +1 -1
- data/app/assets/config/scrapbook_manifest.js +1 -0
- data/app/assets/javascripts/scrapbook/application.js +115 -0
- data/app/assets/stylesheets/scrapbook/application.tailwind.css +18 -5
- data/app/controllers/scrapbook/pages_controller.rb +8 -2
- data/app/helpers/scrapbook/folder_listing_view_model.rb +10 -3
- data/app/helpers/scrapbook/helper_for_view.rb +17 -0
- data/app/models/scrapbook/scrapbook.rb +9 -0
- data/app/views/layouts/scrapbook/_folder_listing.html.erb +25 -4
- data/app/views/layouts/scrapbook/application.html.erb +6 -1
- data/app/views/scrapbook/pages/show.html.erb +3 -1
- data/lib/generators/scrapbook/install_generator.rb +2 -1
- data/lib/scrapbook/engine.rb +1 -3
- data/lib/scrapbook/version.rb +1 -1
- metadata +3 -3
- data/app/mailers/scrapbook/application_mailer.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef6dc0f95ede6ecc1b68f75aaac825101f84252d5f7b8724e2b59534d40c083f
|
4
|
+
data.tar.gz: 6bd20440efd3e0ed318a5d1103c364600163fd48e3fd72f497e221ae07a08cc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e031db1caa0fdc1aea56a3efc5a969b8990305bf3263c7f8445bc7b66908390008465488031819774cfc3404298f9c1eac3cb18ec1c82b122e210f964652c33a
|
7
|
+
data.tar.gz: ff32ea7dad5cadb5f6d88ca444bb803033681f7845c99d4371645e0000da87de6d40609cf46d4c9fa4121cbca36cd2678ba519a49c127ade364fd6616e9d49ae
|
data/README.md
CHANGED
@@ -117,6 +117,12 @@ $> npx tailwindcss -i app/assets/stylesheets/scrapbook/application.tailwind.css
|
|
117
117
|
(Note, the "tailwindcss-rails" gem currently doesn't support Rails engines, so we have to
|
118
118
|
install and run Tailwind manually.)
|
119
119
|
|
120
|
+
## Updating the Turbo javascript
|
121
|
+
|
122
|
+
- Download the compiled JS file from the turbo rails gem. (The releases on the Turbo website
|
123
|
+
didn't include it.)
|
124
|
+
- Comment out or remove the `export` statement towards the end.
|
125
|
+
|
120
126
|
## License
|
121
127
|
|
122
128
|
Copyright 2022 Brad Lindsay
|
@@ -1 +1 @@
|
|
1
|
-
/*! tailwindcss v3.0.23 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input:-ms-input-placeholder,textarea:-ms-input-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;color-adjust:exact}[multiple]{background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:#0000;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:checked:focus,[type=checkbox]:checked:hover,[type=checkbox]:indeterminate,[type=radio]:checked:focus,[type=radio]:checked:hover{border-color:#0000;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:#0000;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px auto -webkit-focus-ring-color}body>nav li{cursor:default}body>nav a,body>nav a:active,body>nav a:hover,body>nav a:visited{color:#0f172a;cursor:default;text-decoration:none;transition:background-color 80ms linear;font-weight:400;font-size:unset;line-height:inherit}body>nav a:hover{background-color:#f0f9ff}body>nav a:active{background-color:#bae6fd}*,:after,:before{--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.block{display:block}.flex{display:flex}.contents{display:contents}.h-screen{height:100vh}.h-full{height:100%}.w-screen{width:100vw}.w-full{width:100%}.min-w-\[20ch\]{min-width:20ch}.max-w-\[50\%\]{max-width:50%}.flex-none{flex:none}.overflow-scroll{overflow:scroll}.border-0{border-width:0}.border-r{border-right-width:1px}.border-solid{border-style:solid}.border-sky-700{--tw-border-opacity:1;border-color:rgb(3 105 161/var(--tw-border-opacity))}.bg-sky-100{--tw-bg-opacity:1;background-color:rgb(224 242 254/var(--tw-bg-opacity))}.\!px-0{padding-left:0!important;padding-right:0!important}.py-2{padding-top:.5rem;padding-bottom:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.text-2xl{font-size:1.5rem;line-height:2rem}.children\:px-4>*{padding-left:1rem;padding-right:1rem}
|
1
|
+
/*! tailwindcss v3.2.1 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:#0000;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:checked:focus,[type=checkbox]:checked:hover,[type=checkbox]:indeterminate,[type=radio]:checked:focus,[type=radio]:checked:hover{border-color:#0000;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:#0000;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}body>nav li{cursor:default}body>nav a,body>nav a:active,body>nav a:hover,body>nav a:visited{color:#0f172a;cursor:default;text-decoration:none;transition:background-color 80ms linear;font-weight:400;font-size:unset;line-height:inherit}turbo-frame{display:block}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::-webkit-backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.block{display:block}.flex{display:flex}.contents{display:contents}.h-screen{height:100vh}.h-full{height:100%}.w-screen{width:100vw}.w-full{width:100%}.min-w-\[20ch\]{min-width:20ch}.max-w-\[50\%\]{max-width:50%}.flex-none{flex:none}.grow{flex-grow:1}.overflow-scroll{overflow:scroll}.border-0{border-width:0}.border-r{border-right-width:1px}.border-solid{border-style:solid}.border-sky-700{--tw-border-opacity:1;border-color:rgb(3 105 161/var(--tw-border-opacity))}.\!px-0{padding-left:0!important;padding-right:0!important}.py-2{padding-top:.5rem;padding-bottom:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.text-2xl{font-size:1.5rem;line-height:2rem}summary{list-style:none}summary::-webkit-details-marker{display:none}details>summary:before{content:"▶︎";font-size:.8rem;flex:none;line-height:1.6rem;margin-right:.4rem;transition:rotate .2s ease-in-out}details[open]>summary:before{rotate:90deg;transition:rotate .2s ease-in-out}.hover\:bg-sky-50:hover{--tw-bg-opacity:1;background-color:rgb(240 249 255/var(--tw-bg-opacity))}.active\:bg-sky-200:active{--tw-bg-opacity:1;background-color:rgb(186 230 253/var(--tw-bg-opacity))}.children\:px-4>*{padding-left:1rem;padding-right:1rem}.\[\&\:has\(\[aria-current\=page\]\)\]\:bg-sky-100:has([aria-current=page]){--tw-bg-opacity:1;background-color:rgb(224 242 254/var(--tw-bg-opacity))}
|
@@ -0,0 +1,115 @@
|
|
1
|
+
//= require scrapbook/turbo.min
|
2
|
+
|
3
|
+
function ready(fn) {
|
4
|
+
if (document.readyState !== 'loading') {
|
5
|
+
fn()
|
6
|
+
} else {
|
7
|
+
document.addEventListener('DOMContentLoaded', fn)
|
8
|
+
}
|
9
|
+
}
|
10
|
+
ready(() => {
|
11
|
+
const scrapbook_root_path = document.head.querySelector("meta[name=scrapbook-root]").content
|
12
|
+
|
13
|
+
function buildInitialTree() {
|
14
|
+
const paths = window.location.pathname.substring(scrapbook_root_path.length).split("/")
|
15
|
+
if (paths.length === 1 && paths[0] === "") { return }
|
16
|
+
|
17
|
+
fetch(scrapbook_root_path)
|
18
|
+
.then((response) => response.text())
|
19
|
+
.then((data) => {
|
20
|
+
const root = document.createElement('html')
|
21
|
+
const nav = document.getElementById('folder_listing')
|
22
|
+
const frame = nav.querySelector('turbo-frame')
|
23
|
+
|
24
|
+
root.innerHTML = data
|
25
|
+
// Keep the nav element to keep listeners on it intact.
|
26
|
+
nav.innerHTML = root.querySelector('#folder_listing').innerHTML
|
27
|
+
setCurrent()
|
28
|
+
|
29
|
+
openFolderPath(window.location.pathname, scrapbook_root_path + paths[0])
|
30
|
+
})
|
31
|
+
.catch((error) => {
|
32
|
+
console.error("Unknown error:", error)
|
33
|
+
})
|
34
|
+
}
|
35
|
+
|
36
|
+
function openFolderPath(path, currentSubPath = scrapbook_root_path) {
|
37
|
+
const frame = document.querySelector('turbo-frame[src="' + currentSubPath + '"]')
|
38
|
+
if (!frame) { return }
|
39
|
+
|
40
|
+
if (path !== currentSubPath)
|
41
|
+
frame.addEventListener('turbo:frame-render', () => {
|
42
|
+
nextSegment = path.replace(currentSubPath + '/', '').split('/')[0]
|
43
|
+
openFolderPath(path, currentSubPath + '/' + nextSegment)
|
44
|
+
}, {once: true})
|
45
|
+
frame.parentElement.open = true
|
46
|
+
}
|
47
|
+
|
48
|
+
function runOpenFor(ids) {
|
49
|
+
const idsLeft = []
|
50
|
+
const framesFound = []
|
51
|
+
|
52
|
+
ids.forEach((id) => {
|
53
|
+
let frame = document.getElementById(id)
|
54
|
+
!frame ? idsLeft.push(id) : framesFound.push(frame)
|
55
|
+
})
|
56
|
+
|
57
|
+
framesFound.forEach((frame) => {
|
58
|
+
frame.addEventListener('turbo:frame-render', () => {
|
59
|
+
runOpenFor(idsLeft)
|
60
|
+
}, {once: true})
|
61
|
+
frame.parentElement.open = true
|
62
|
+
})
|
63
|
+
}
|
64
|
+
|
65
|
+
function setCurrent(link = document.querySelector('#folder_listing a[href="' + window.location.pathname + '"]')) {
|
66
|
+
if (link === null) { return }
|
67
|
+
|
68
|
+
oldSelection = document.querySelector('#folder_listing a[aria-current="page"]')
|
69
|
+
if (oldSelection == link) { return }
|
70
|
+
|
71
|
+
if (oldSelection) {
|
72
|
+
oldSelection.removeAttribute('aria-current', 'page')
|
73
|
+
}
|
74
|
+
|
75
|
+
link.setAttribute('aria-current', 'page')
|
76
|
+
}
|
77
|
+
|
78
|
+
|
79
|
+
buildInitialTree()
|
80
|
+
folderListingElem = document.getElementById("folder_listing")
|
81
|
+
|
82
|
+
// Update selection when a link is clicked
|
83
|
+
folderListingElem.addEventListener('click', (e) => {
|
84
|
+
const target = e.target
|
85
|
+
if (target.tagName != 'A') { return }
|
86
|
+
|
87
|
+
setCurrent(target)
|
88
|
+
})
|
89
|
+
|
90
|
+
// Every time a folder is opened, it's possible to be re-revealing the selected page.
|
91
|
+
folderListingElem.addEventListener('turbo:frame-render', () => {
|
92
|
+
setCurrent()
|
93
|
+
})
|
94
|
+
|
95
|
+
// Refresh trees when a folder is toggled back open
|
96
|
+
// The first time a details element is toggled open, the turbo frame lazily loads. This
|
97
|
+
// adds support for reloading whenever the element is closed and then re-opened. All
|
98
|
+
// turbo frames of any nested folders are also refreshed.
|
99
|
+
folderListingElem.addEventListener('toggle', (e) => {
|
100
|
+
if (!e.target.open) { return }
|
101
|
+
if ('loadedOnce' in e.target.dataset === false) {
|
102
|
+
e.target.dataset.loadedOnce = true
|
103
|
+
return
|
104
|
+
}
|
105
|
+
|
106
|
+
const idsToOpen = []
|
107
|
+
e.target.querySelectorAll('details[open] > turbo-frame').forEach(elem => idsToOpen.push(elem.id))
|
108
|
+
|
109
|
+
const firstFrame = document.getElementById(idsToOpen.shift())
|
110
|
+
firstFrame.addEventListener('turbo:frame-render', () => {
|
111
|
+
runOpenFor(idsToOpen)
|
112
|
+
}, {once: true})
|
113
|
+
firstFrame.reload()
|
114
|
+
}, {capture: true})
|
115
|
+
})
|
@@ -22,11 +22,24 @@
|
|
22
22
|
line-height:inherit;
|
23
23
|
}
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
turbo-frame {
|
26
|
+
display: block;
|
27
27
|
}
|
28
|
+
}
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
summary { list-style: none; }
|
31
|
+
summary::-webkit-details-marker { display: none; }
|
32
|
+
|
33
|
+
details > summary::before {
|
34
|
+
content: "▶︎";
|
35
|
+
font-size: 0.8rem;
|
36
|
+
flex: none;
|
37
|
+
line-height: 1.6rem;
|
38
|
+
margin-right: 0.4rem;
|
39
|
+
transition: rotate 0.2s ease-in-out;
|
40
|
+
}
|
41
|
+
|
42
|
+
details[open] > summary::before {
|
43
|
+
rotate: 90deg;
|
44
|
+
transition: rotate 0.2s ease-in-out;
|
32
45
|
}
|
@@ -5,13 +5,19 @@ module Scrapbook
|
|
5
5
|
class PagesController < ApplicationController
|
6
6
|
self.view_paths = Engine.config.paths['app/views'].to_a
|
7
7
|
|
8
|
+
layout -> { false if request.headers.include?('Turbo-Frame') }
|
9
|
+
|
8
10
|
def show
|
9
11
|
return head(:not_found) if (scrapbook = find_scrapbook).nil?
|
10
12
|
|
11
13
|
pathname = calculate_pathname(scrapbook, params[:id])
|
12
|
-
template = calculate_template
|
13
14
|
|
14
|
-
|
15
|
+
if request.headers['Turbo-Frame']&.start_with?('path_')
|
16
|
+
render partial: 'layouts/scrapbook/folder_listing',
|
17
|
+
locals: {scrapbook: scrapbook, pathname: pathname}
|
18
|
+
else
|
19
|
+
render locals: {scrapbook: scrapbook, pathname: pathname}, formats: [:html]
|
20
|
+
end
|
15
21
|
end
|
16
22
|
|
17
23
|
def raw
|
@@ -3,12 +3,13 @@
|
|
3
3
|
module Scrapbook
|
4
4
|
# Model to assest list a folder's contents
|
5
5
|
class FolderListingViewModel
|
6
|
-
attr_reader :view, :scrapbook, :pathname, :files, :folders
|
6
|
+
attr_reader :view, :scrapbook, :pathname, :files, :folders, :depth
|
7
7
|
|
8
8
|
def initialize(view, scrapbook, pathname)
|
9
9
|
self.view = view
|
10
10
|
self.scrapbook = scrapbook
|
11
11
|
self.pathname = pathname.directory? ? pathname : pathname.dirname
|
12
|
+
self.depth = calculate_depth
|
12
13
|
self.folders, self.files = split_files_and_folders
|
13
14
|
end
|
14
15
|
|
@@ -24,12 +25,18 @@ module Scrapbook
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def header_name
|
27
|
-
root? ?
|
28
|
+
root? ? scrapbook.name : pathname.basename.to_s
|
28
29
|
end
|
29
30
|
|
30
31
|
private
|
31
32
|
|
32
|
-
attr_writer :view, :scrapbook, :pathname, :files, :folders
|
33
|
+
attr_writer :view, :scrapbook, :pathname, :files, :folders, :depth
|
34
|
+
|
35
|
+
def calculate_depth
|
36
|
+
return 0 if pathname == scrapbook.pages_pathname
|
37
|
+
|
38
|
+
scrapbook.relative_page_pathname_for(pathname).descend.count
|
39
|
+
end
|
33
40
|
|
34
41
|
def split_files_and_folders
|
35
42
|
helper = HelperForView.new(view)
|
@@ -13,6 +13,23 @@ module Scrapbook
|
|
13
13
|
view.short_page_path(scrapbook.relative_page_path_for(pathname))
|
14
14
|
end
|
15
15
|
|
16
|
+
def nav_link_for(scrapbook:, pathname:, is_current: false, depth: 0, **kwargs)
|
17
|
+
link_name = pathname == scrapbook.pages_pathname ? scrapbook.name : pathname.basename
|
18
|
+
link_attrs = {
|
19
|
+
data: {'turbo-frame': 'page_content'},
|
20
|
+
class: %w[block w-100],
|
21
|
+
aria: {}
|
22
|
+
}
|
23
|
+
link_attrs[:style] = "padding-left: #{depth}rem;" if depth != 0
|
24
|
+
link_attrs[:aria][:current] = 'page' if is_current
|
25
|
+
link_attrs[:class].concat(Array(kwargs.delete(:class))) if kwargs.include?(:class)
|
26
|
+
link_attrs[:data].merge!(kwargs.delete(:data)) if kwargs.include?(:data)
|
27
|
+
link_attrs[:aria].merge!(kwargs.delete(:aria)) if kwargs.include?(:aria)
|
28
|
+
link_attrs.merge!(kwargs)
|
29
|
+
|
30
|
+
view.link_to(link_name, short_path_to(pathname, scrapbook), **link_attrs)
|
31
|
+
end
|
32
|
+
|
16
33
|
def remove_handler_exts_from(pathname)
|
17
34
|
pathname.dirname.join(
|
18
35
|
pathname.basename.sub(/(?:.#{view.lookup_context.handlers.join('|.')})+\z/, '')
|
@@ -43,6 +43,15 @@ module Scrapbook
|
|
43
43
|
relative_path
|
44
44
|
end
|
45
45
|
|
46
|
+
def relative_page_pathname_for(pathname)
|
47
|
+
relative_path = pathname.relative_path_from(pages_pathname)
|
48
|
+
if relative_path.to_s.start_with?('..')
|
49
|
+
raise ArgumentError, "Pathname isn't inside the scrapbook pages: #{relative_path}"
|
50
|
+
end
|
51
|
+
|
52
|
+
relative_path
|
53
|
+
end
|
54
|
+
|
46
55
|
def ==(other)
|
47
56
|
other.class == self.class && other.root == root
|
48
57
|
end
|
@@ -2,8 +2,29 @@
|
|
2
2
|
helper = Scrapbook::HelperForView.new(self)
|
3
3
|
listing = Scrapbook::FolderListingViewModel.new(self, scrapbook, pathname)
|
4
4
|
pathname_without_handler_exts = helper.remove_handler_exts_from(pathname)
|
5
|
+
indentation_depth = (local_assigns[:nav_depth] || listing.depth) + 1
|
6
|
+
selection_classes = "active:bg-sky-200 hover:bg-sky-50 [&:has([aria-current=page])]:bg-sky-100"
|
5
7
|
%>
|
6
|
-
<% unless listing.root? %><%= link_to "‹ #{listing.parent_display_name}", helper.short_path_to(listing.pathname.parent), class: 'back-to-parent block w-100' %><% end %>
|
7
|
-
<header aria-label="Which folder's contents" class="text-2xl
|
8
|
-
|
9
|
-
|
8
|
+
<% unless listing.root? %><%= link_to "‹ #{listing.parent_display_name}", helper.short_path_to(listing.pathname.parent, scrapbook), class: 'back-to-parent block w-100' %><% end %>
|
9
|
+
<header aria-label="Which folder's contents" class="text-2xl !px-0 children:px-4 <%= selection_classes %>">
|
10
|
+
<%= helper.nav_link_for(scrapbook: scrapbook, pathname: listing.pathname, is_current: pathname == listing.pathname) %>
|
11
|
+
</header>
|
12
|
+
<turbo-frame id="path_<%= pathname.hash %>">
|
13
|
+
<ul aria-label="Sub-folders">
|
14
|
+
<% listing.folders.each do |folder| %>
|
15
|
+
<li>
|
16
|
+
<details>
|
17
|
+
<summary class="flex <%= selection_classes %>" style="padding-left: <%= indentation_depth %>rem;">
|
18
|
+
<%= helper.nav_link_for(scrapbook: scrapbook, pathname: folder, class: 'grow') %>
|
19
|
+
</summary>
|
20
|
+
<turbo-frame id="path_<%= folder.hash %>" src="<%= helper.short_path_to(folder, scrapbook) %>" loading="lazy"></turbo-frame>
|
21
|
+
</details>
|
22
|
+
</li>
|
23
|
+
<% end %>
|
24
|
+
</ul>
|
25
|
+
<ul aria-label="Sub-files">
|
26
|
+
<% listing.files.each do |file| %><% next if listing.folders.include?(file) %>
|
27
|
+
<li class="<%= selection_classes %>"><%= helper.nav_link_for(scrapbook: scrapbook, pathname: file, is_current: file == pathname_without_handler_exts, depth: indentation_depth) %></li>
|
28
|
+
<% end %>
|
29
|
+
</ul>
|
30
|
+
</turbo-frame>
|
@@ -6,9 +6,14 @@
|
|
6
6
|
<%= csp_meta_tag %>
|
7
7
|
|
8
8
|
<%= stylesheet_link_tag "scrapbook/application", media: "all", "data-turbo-track": "reload" %>
|
9
|
+
<%= javascript_include_tag "scrapbook/application" %>
|
10
|
+
<meta name="scrapbook-root" content="<%= root_path %>">
|
9
11
|
</head>
|
10
12
|
<body class="flex">
|
11
|
-
<nav class="flex-none min-w-[20ch] max-w-[50%] h-screen overflow-scroll
|
13
|
+
<nav id="folder_listing" class="flex-none min-w-[20ch] max-w-[50%] h-screen overflow-scroll border-solid border-sky-700 border-0 border-r"><%= render 'layouts/scrapbook/folder_listing', scrapbook: local_assigns[:scrapbook], pathname: local_assigns[:pathname], nav_depth: 0 %></nav>
|
12
14
|
<main class="py-2 px-4 h-screen w-screen overflow-scroll"><%= yield %></main>
|
15
|
+
<script type="text/javascript">
|
16
|
+
|
17
|
+
</script>
|
13
18
|
</body>
|
14
19
|
</html>
|
@@ -1 +1,3 @@
|
|
1
|
-
<
|
1
|
+
<turbo-frame id="page_content" class="w-full h-full" data-turbo-action="advance">
|
2
|
+
<iframe src="<%= raw_page_path(scrapbook.relative_page_path_for(pathname)) %>" class="w-full h-full"></iframe>
|
3
|
+
</turbo-frame>
|
@@ -21,7 +21,8 @@ module Scrapbook
|
|
21
21
|
relative_path = 'app/assets/config/manifest.js'
|
22
22
|
return unless FileTest.exist?(File.expand_path(relative_path, destination_root))
|
23
23
|
|
24
|
-
insert_into_file(relative_path,
|
24
|
+
insert_into_file(relative_path, "//= link scrapbook/application.css\n")
|
25
|
+
insert_into_file(relative_path, "//= link scrapbook/application.js\n")
|
25
26
|
end
|
26
27
|
end
|
27
28
|
end
|
data/lib/scrapbook/engine.rb
CHANGED
@@ -11,9 +11,7 @@ module Scrapbook
|
|
11
11
|
|
12
12
|
initializer 'scrapbook.assets' do |app|
|
13
13
|
if app.config.scrapbook.precompile_assets && app.config.respond_to?(:assets)
|
14
|
-
app.config.assets.precompile.
|
15
|
-
scrapbook/application.css
|
16
|
-
]
|
14
|
+
app.config.assets.precompile.push('scrapbook/application.css')
|
17
15
|
end
|
18
16
|
end
|
19
17
|
end
|
data/lib/scrapbook/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scrapbook
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brad Lindsay
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-06-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -43,6 +43,7 @@ files:
|
|
43
43
|
- Rakefile
|
44
44
|
- app/assets/builds/scrapbook/application.css
|
45
45
|
- app/assets/config/scrapbook_manifest.js
|
46
|
+
- app/assets/javascripts/scrapbook/application.js
|
46
47
|
- app/assets/stylesheets/scrapbook/application.tailwind.css
|
47
48
|
- app/controllers/scrapbook/application_controller.rb
|
48
49
|
- app/controllers/scrapbook/empty_controller.rb
|
@@ -50,7 +51,6 @@ files:
|
|
50
51
|
- app/helpers/scrapbook/application_helper.rb
|
51
52
|
- app/helpers/scrapbook/folder_listing_view_model.rb
|
52
53
|
- app/helpers/scrapbook/helper_for_view.rb
|
53
|
-
- app/mailers/scrapbook/application_mailer.rb
|
54
54
|
- app/models/scrapbook/scrapbook.rb
|
55
55
|
- app/views/layouts/scrapbook/_folder_listing.html.erb
|
56
56
|
- app/views/layouts/scrapbook/application.html.erb
|