superglue 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/lib/generators/rails/scaffold_controller_generator.rb +12 -0
  3. data/lib/generators/rails/superglue_generator.rb +92 -0
  4. data/lib/generators/rails/templates/_form.json.props +13 -0
  5. data/lib/generators/rails/templates/controller.rb.tt +82 -0
  6. data/lib/generators/rails/templates/edit.json.props +14 -0
  7. data/lib/generators/rails/templates/index.json.props +13 -0
  8. data/lib/generators/rails/templates/new.json.props +15 -0
  9. data/lib/generators/rails/templates/show.json.props +7 -0
  10. data/lib/generators/rails/templates/web/edit.html.erb +12 -0
  11. data/lib/generators/rails/templates/web/edit.js +31 -0
  12. data/lib/generators/rails/templates/web/index.html.erb +7 -0
  13. data/lib/generators/rails/templates/web/index.js +49 -0
  14. data/lib/generators/rails/templates/web/new.html.erb +7 -0
  15. data/lib/generators/rails/templates/web/new.js +29 -0
  16. data/lib/generators/rails/templates/web/show.html.erb +7 -0
  17. data/lib/generators/rails/templates/web/show.js +28 -0
  18. data/lib/install/templates/web/action_creators.js +14 -0
  19. data/lib/install/templates/web/actions.js +4 -0
  20. data/lib/install/templates/web/application.js +114 -0
  21. data/lib/install/templates/web/application.json.props +27 -0
  22. data/lib/install/templates/web/application_visit.js +65 -0
  23. data/lib/install/templates/web/initializer.rb +1 -0
  24. data/lib/install/templates/web/reducer.js +72 -0
  25. data/lib/install/web.rb +66 -0
  26. data/lib/superglue/helpers.rb +552 -0
  27. data/lib/superglue/redirection.rb +30 -0
  28. data/lib/superglue.rb +38 -0
  29. data/lib/tasks/install.rake +42 -0
  30. data/test/engine_test.rb +7 -0
  31. data/test/helpers_test.rb +23 -0
  32. data/test/render_test.rb +81 -0
  33. data/test/test_helper.rb +20 -0
  34. metadata +218 -0
@@ -0,0 +1 @@
1
+ require 'props_template/core_ext'
@@ -0,0 +1,72 @@
1
+ // Example:
2
+ //
3
+ // import {
4
+ // CLEAR_FORM_ERRORS
5
+ // } from './actions'
6
+ // import produce from "immer"
7
+ //
8
+ // export const applicationPagesReducer = (state = {}, action) => {
9
+ // switch(action.type) {
10
+ // case CLEAR_FORM_ERRORS: {
11
+ // const {pageKey} = action.payload
12
+ //
13
+ // return produce(state, draft => {
14
+ // const currentPage = draft[pageKey]
15
+ // delete currentPage.errors
16
+ // })
17
+ // }
18
+ // default:
19
+ // return state
20
+ // }
21
+ // }
22
+
23
+ import {
24
+ REHYDRATE,
25
+ } from './actions'
26
+
27
+ // The applicationPageReducer is for cross page reducers
28
+ // Its common to add to this. You'll typically have to pass a pageKey to the
29
+ // action payload to distinguish the current page
30
+ //
31
+ // The pageKey is passed through the props in your component. Access it like
32
+ // this: `this.props.pageKey` then dispatch it in an action
33
+ export const applicationPagesReducer = (state = {}, action) => {
34
+ switch(action.type) {
35
+ default:
36
+ return state
37
+ }
38
+ }
39
+
40
+ // The applicationRootReducer is for app wide reducers
41
+ // Its rare to be adding to this. Included out of the box ix a reducer for
42
+ // Redux Persist.
43
+ //
44
+ // The REHYDRATE reducer is generated by Superglue and is needed to persist state
45
+ // on any changes made to the initial state that gets injected into
46
+ // window.SUPERGLUE_INITIAL_PAGE_STATE.
47
+ export const applicationRootReducer = (state = {}, action) => {
48
+ switch(action.type) {
49
+ case REHYDRATE: {
50
+ if (action.payload) {
51
+ const {
52
+ pages: hydratedPages
53
+ } = action.payload
54
+ const { pages } = state
55
+ const nextPages = { ...pages, ...hydratedPages }
56
+
57
+ for (const key in pages) {
58
+ if (pages[key] && hydratedPages[key] &&
59
+ pages[key].renderedAt > hydratedPages[key].renderedAt) {
60
+ nextPages[key] = { ...pages[key] }
61
+ }
62
+ }
63
+
64
+ return { ...state, pages: nextPages }
65
+ } else {
66
+ return state
67
+ }
68
+ }
69
+ default:
70
+ return state
71
+ }
72
+ }
@@ -0,0 +1,66 @@
1
+ require "webpacker/configuration"
2
+
3
+ babel_config = Rails.root.join("babel.config.js")
4
+
5
+ def add_member_methods
6
+ inject_into_file "app/models/application_record.rb", after: "class ApplicationRecord < ActiveRecord::Base\n" do
7
+ <<-RUBY
8
+ def self.member_at(index)
9
+ offset(index).limit(1).first
10
+ end
11
+
12
+ def self.member_by(attr, value)
13
+ find_by(Hash[attr, value])
14
+ end
15
+ RUBY
16
+ end
17
+ end
18
+
19
+ say "Copying module-resolver preset to your babel.config.js"
20
+ resolver_snippet = <<~JAVASCRIPT
21
+ [
22
+ require('babel-plugin-module-resolver').default, {
23
+ "root": ["./app"],
24
+ "alias": {
25
+ "views": "./app/views",
26
+ "components": "./app/components",
27
+ "javascript": "./app/javascript"
28
+ }
29
+ }
30
+ ],
31
+ JAVASCRIPT
32
+ insert_into_file "babel.config.js", resolver_snippet, after: /plugins: \[\n/
33
+
34
+ say "Copying application.js file to #{Webpacker.config.source_entry_path}"
35
+ copy_file "#{__dir__}/templates/web/application.js", "#{Webpacker.config.source_entry_path}/application.js"
36
+
37
+ say "Copying reducer.js file to #{Webpacker.config.source_entry_path}"
38
+ copy_file "#{__dir__}/templates/web/reducer.js", "#{Webpacker.config.source_entry_path}/reducer.js"
39
+
40
+ say "Copying action_creators.js file to #{Webpacker.config.source_entry_path}"
41
+ copy_file "#{__dir__}/templates/web/action_creators.js", "#{Webpacker.config.source_entry_path}/action_creators.js"
42
+
43
+ say "Copying actions.js file to #{Webpacker.config.source_entry_path}"
44
+ copy_file "#{__dir__}/templates/web/actions.js", "#{Webpacker.config.source_entry_path}/actions.js"
45
+
46
+ say "Copying application_visit.js file to #{Webpacker.config.source_entry_path}"
47
+ copy_file "#{__dir__}/templates/web/application_visit.js", "#{Webpacker.config.source_entry_path}/application_visit.js"
48
+
49
+ say "Copying Superglue initializer"
50
+ copy_file "#{__dir__}/templates/web/initializer.rb", "config/initializers/superglue.rb"
51
+
52
+ say "Copying application.json.props"
53
+ copy_file "#{__dir__}/templates/web/application.json.props", "app/views/layouts/application.json.props"
54
+
55
+ say "Adding required member methods to ApplicationRecord"
56
+ add_member_methods
57
+
58
+ say "Installing React, Redux, and Superglue"
59
+ run "yarn add babel-plugin-module-resolver history html-react-parser react-redux redux-thunk redux redux-persist reduce-reducers immer @thoughtbot/superglue --save"
60
+
61
+ # For newer webpacker
62
+ insert_into_file Webpacker.config.config_path, "'app/views', 'app/components'", after: /additional_paths: \[/
63
+ # For older webpacker
64
+ insert_into_file Webpacker.config.config_path, "'app/views', 'app/components'", after: /resolved_paths: \[/
65
+
66
+ say "Webpacker now supports superglue.js 🎉", :green
@@ -0,0 +1,552 @@
1
+ module Superglue
2
+ module Helpers
3
+ POSSIBLE_STANDARD_NAMES = {
4
+ # HTML
5
+ accept: 'accept',
6
+ acceptcharset: 'acceptCharset',
7
+ 'accept-charset': 'acceptCharset',
8
+ accesskey: 'accessKey',
9
+ action: 'action',
10
+ allowfullscreen: 'allowFullScreen',
11
+ alt: 'alt',
12
+ as: 'as',
13
+ async: 'async',
14
+ autocapitalize: 'autoCapitalize',
15
+ autocomplete: 'autoComplete',
16
+ autocorrect: 'autoCorrect',
17
+ autofocus: 'autoFocus',
18
+ autoplay: 'autoPlay',
19
+ autosave: 'autoSave',
20
+ capture: 'capture',
21
+ cellpadding: 'cellPadding',
22
+ cellspacing: 'cellSpacing',
23
+ challenge: 'challenge',
24
+ charset: 'charSet',
25
+ checked: 'checked',
26
+ children: 'children',
27
+ cite: 'cite',
28
+ class: 'className',
29
+ classid: 'classID',
30
+ classname: 'className',
31
+ cols: 'cols',
32
+ colspan: 'colSpan',
33
+ content: 'content',
34
+ contenteditable: 'contentEditable',
35
+ contextmenu: 'contextMenu',
36
+ controls: 'controls',
37
+ controlslist: 'controlsList',
38
+ coords: 'coords',
39
+ crossorigin: 'crossOrigin',
40
+ dangerouslysetinnerhtml: 'dangerouslySetInnerHTML',
41
+ data: 'data',
42
+ datetime: 'dateTime',
43
+ default: 'default',
44
+ defaultchecked: 'defaultChecked',
45
+ defaultvalue: 'defaultValue',
46
+ defer: 'defer',
47
+ dir: 'dir',
48
+ disabled: 'disabled',
49
+ disablepictureinpicture: 'disablePictureInPicture',
50
+ disableremoteplayback: 'disableRemotePlayback',
51
+ download: 'download',
52
+ draggable: 'draggable',
53
+ enctype: 'encType',
54
+ for: 'htmlFor',
55
+ form: 'form',
56
+ formmethod: 'formMethod',
57
+ formaction: 'formAction',
58
+ formenctype: 'formEncType',
59
+ formnovalidate: 'formNoValidate',
60
+ formtarget: 'formTarget',
61
+ frameborder: 'frameBorder',
62
+ headers: 'headers',
63
+ height: 'height',
64
+ hidden: 'hidden',
65
+ high: 'high',
66
+ href: 'href',
67
+ hreflang: 'hrefLang',
68
+ htmlfor: 'htmlFor',
69
+ httpequiv: 'httpEquiv',
70
+ 'http-equiv': 'httpEquiv',
71
+ icon: 'icon',
72
+ id: 'id',
73
+ innerhtml: 'innerHTML',
74
+ inputmode: 'inputMode',
75
+ integrity: 'integrity',
76
+ is: 'is',
77
+ itemid: 'itemID',
78
+ itemprop: 'itemProp',
79
+ itemref: 'itemRef',
80
+ itemscope: 'itemScope',
81
+ itemtype: 'itemType',
82
+ keyparams: 'keyParams',
83
+ keytype: 'keyType',
84
+ kind: 'kind',
85
+ label: 'label',
86
+ lang: 'lang',
87
+ list: 'list',
88
+ loop: 'loop',
89
+ low: 'low',
90
+ manifest: 'manifest',
91
+ marginwidth: 'marginWidth',
92
+ marginheight: 'marginHeight',
93
+ max: 'max',
94
+ maxlength: 'maxLength',
95
+ media: 'media',
96
+ mediagroup: 'mediaGroup',
97
+ method: 'method',
98
+ min: 'min',
99
+ minlength: 'minLength',
100
+ multiple: 'multiple',
101
+ muted: 'muted',
102
+ name: 'name',
103
+ nomodule: 'noModule',
104
+ nonce: 'nonce',
105
+ novalidate: 'noValidate',
106
+ open: 'open',
107
+ optimum: 'optimum',
108
+ pattern: 'pattern',
109
+ placeholder: 'placeholder',
110
+ playsinline: 'playsInline',
111
+ poster: 'poster',
112
+ preload: 'preload',
113
+ profile: 'profile',
114
+ radiogroup: 'radioGroup',
115
+ readonly: 'readOnly',
116
+ referrerpolicy: 'referrerPolicy',
117
+ rel: 'rel',
118
+ required: 'required',
119
+ reversed: 'reversed',
120
+ role: 'role',
121
+ rows: 'rows',
122
+ rowspan: 'rowSpan',
123
+ sandbox: 'sandbox',
124
+ scope: 'scope',
125
+ scoped: 'scoped',
126
+ scrolling: 'scrolling',
127
+ seamless: 'seamless',
128
+ selected: 'selected',
129
+ shape: 'shape',
130
+ size: 'size',
131
+ sizes: 'sizes',
132
+ span: 'span',
133
+ spellcheck: 'spellCheck',
134
+ src: 'src',
135
+ srcdoc: 'srcDoc',
136
+ srclang: 'srcLang',
137
+ srcset: 'srcSet',
138
+ start: 'start',
139
+ step: 'step',
140
+ style: 'style',
141
+ summary: 'summary',
142
+ tabindex: 'tabIndex',
143
+ target: 'target',
144
+ title: 'title',
145
+ type: 'type',
146
+ usemap: 'useMap',
147
+ value: 'value',
148
+ width: 'width',
149
+ wmode: 'wmode',
150
+ wrap: 'wrap',
151
+
152
+ # SVG
153
+ about: 'about',
154
+ accentheight: 'accentHeight',
155
+ 'accent-height': 'accentHeight',
156
+ accumulate: 'accumulate',
157
+ additive: 'additive',
158
+ alignmentbaseline: 'alignmentBaseline',
159
+ 'alignment-baseline': 'alignmentBaseline',
160
+ allowreorder: 'allowReorder',
161
+ alphabetic: 'alphabetic',
162
+ amplitude: 'amplitude',
163
+ arabicform: 'arabicForm',
164
+ 'arabic-form': 'arabicForm',
165
+ ascent: 'ascent',
166
+ attributename: 'attributeName',
167
+ attributetype: 'attributeType',
168
+ autoreverse: 'autoReverse',
169
+ azimuth: 'azimuth',
170
+ basefrequency: 'baseFrequency',
171
+ baselineshift: 'baselineShift',
172
+ 'baseline-shift': 'baselineShift',
173
+ baseprofile: 'baseProfile',
174
+ bbox: 'bbox',
175
+ begin: 'begin',
176
+ bias: 'bias',
177
+ by: 'by',
178
+ calcmode: 'calcMode',
179
+ capheight: 'capHeight',
180
+ 'cap-height': 'capHeight',
181
+ clip: 'clip',
182
+ clippath: 'clipPath',
183
+ 'clip-path': 'clipPath',
184
+ clippathunits: 'clipPathUnits',
185
+ cliprule: 'clipRule',
186
+ 'clip-rule': 'clipRule',
187
+ color: 'color',
188
+ colorinterpolation: 'colorInterpolation',
189
+ 'color-interpolation': 'colorInterpolation',
190
+ colorinterpolationfilters: 'colorInterpolationFilters',
191
+ 'color-interpolation-filters': 'colorInterpolationFilters',
192
+ colorprofile: 'colorProfile',
193
+ 'color-profile': 'colorProfile',
194
+ colorrendering: 'colorRendering',
195
+ 'color-rendering': 'colorRendering',
196
+ contentscripttype: 'contentScriptType',
197
+ contentstyletype: 'contentStyleType',
198
+ cursor: 'cursor',
199
+ cx: 'cx',
200
+ cy: 'cy',
201
+ d: 'd',
202
+ datatype: 'datatype',
203
+ decelerate: 'decelerate',
204
+ descent: 'descent',
205
+ diffuseconstant: 'diffuseConstant',
206
+ direction: 'direction',
207
+ display: 'display',
208
+ divisor: 'divisor',
209
+ dominantbaseline: 'dominantBaseline',
210
+ 'dominant-baseline': 'dominantBaseline',
211
+ dur: 'dur',
212
+ dx: 'dx',
213
+ dy: 'dy',
214
+ edgemode: 'edgeMode',
215
+ elevation: 'elevation',
216
+ enablebackground: 'enableBackground',
217
+ 'enable-background': 'enableBackground',
218
+ end: 'end',
219
+ exponent: 'exponent',
220
+ externalresourcesrequired: 'externalResourcesRequired',
221
+ fill: 'fill',
222
+ fillopacity: 'fillOpacity',
223
+ 'fill-opacity': 'fillOpacity',
224
+ fillrule: 'fillRule',
225
+ 'fill-rule': 'fillRule',
226
+ filter: 'filter',
227
+ filterres: 'filterRes',
228
+ filterunits: 'filterUnits',
229
+ floodopacity: 'floodOpacity',
230
+ 'flood-opacity': 'floodOpacity',
231
+ floodcolor: 'floodColor',
232
+ 'flood-color': 'floodColor',
233
+ focusable: 'focusable',
234
+ fontfamily: 'fontFamily',
235
+ 'font-family': 'fontFamily',
236
+ fontsize: 'fontSize',
237
+ 'font-size': 'fontSize',
238
+ fontsizeadjust: 'fontSizeAdjust',
239
+ 'font-size-adjust': 'fontSizeAdjust',
240
+ fontstretch: 'fontStretch',
241
+ 'font-stretch': 'fontStretch',
242
+ fontstyle: 'fontStyle',
243
+ 'font-style': 'fontStyle',
244
+ fontvariant: 'fontVariant',
245
+ 'font-variant': 'fontVariant',
246
+ fontweight: 'fontWeight',
247
+ 'font-weight': 'fontWeight',
248
+ format: 'format',
249
+ from: 'from',
250
+ fx: 'fx',
251
+ fy: 'fy',
252
+ g1: 'g1',
253
+ g2: 'g2',
254
+ glyphname: 'glyphName',
255
+ 'glyph-name': 'glyphName',
256
+ glyphorientationhorizontal: 'glyphOrientationHorizontal',
257
+ 'glyph-orientation-horizontal': 'glyphOrientationHorizontal',
258
+ glyphorientationvertical: 'glyphOrientationVertical',
259
+ 'glyph-orientation-vertical': 'glyphOrientationVertical',
260
+ glyphref: 'glyphRef',
261
+ gradienttransform: 'gradientTransform',
262
+ gradientunits: 'gradientUnits',
263
+ hanging: 'hanging',
264
+ horizadvx: 'horizAdvX',
265
+ 'horiz-adv-x': 'horizAdvX',
266
+ horizoriginx: 'horizOriginX',
267
+ 'horiz-origin-x': 'horizOriginX',
268
+ ideographic: 'ideographic',
269
+ imagerendering: 'imageRendering',
270
+ 'image-rendering': 'imageRendering',
271
+ in2: 'in2',
272
+ in: 'in',
273
+ inlist: 'inlist',
274
+ intercept: 'intercept',
275
+ k1: 'k1',
276
+ k2: 'k2',
277
+ k3: 'k3',
278
+ k4: 'k4',
279
+ k: 'k',
280
+ kernelmatrix: 'kernelMatrix',
281
+ kernelunitlength: 'kernelUnitLength',
282
+ kerning: 'kerning',
283
+ keypoints: 'keyPoints',
284
+ keysplines: 'keySplines',
285
+ keytimes: 'keyTimes',
286
+ lengthadjust: 'lengthAdjust',
287
+ letterspacing: 'letterSpacing',
288
+ 'letter-spacing': 'letterSpacing',
289
+ lightingcolor: 'lightingColor',
290
+ 'lighting-color': 'lightingColor',
291
+ limitingconeangle: 'limitingConeAngle',
292
+ local: 'local',
293
+ markerend: 'markerEnd',
294
+ 'marker-end': 'markerEnd',
295
+ markerheight: 'markerHeight',
296
+ markermid: 'markerMid',
297
+ 'marker-mid': 'markerMid',
298
+ markerstart: 'markerStart',
299
+ 'marker-start': 'markerStart',
300
+ markerunits: 'markerUnits',
301
+ markerwidth: 'markerWidth',
302
+ mask: 'mask',
303
+ maskcontentunits: 'maskContentUnits',
304
+ maskunits: 'maskUnits',
305
+ mathematical: 'mathematical',
306
+ mode: 'mode',
307
+ numoctaves: 'numOctaves',
308
+ offset: 'offset',
309
+ opacity: 'opacity',
310
+ operator: 'operator',
311
+ order: 'order',
312
+ orient: 'orient',
313
+ orientation: 'orientation',
314
+ origin: 'origin',
315
+ overflow: 'overflow',
316
+ overlineposition: 'overlinePosition',
317
+ 'overline-position': 'overlinePosition',
318
+ overlinethickness: 'overlineThickness',
319
+ 'overline-thickness': 'overlineThickness',
320
+ paintorder: 'paintOrder',
321
+ 'paint-order': 'paintOrder',
322
+ panose1: 'panose1',
323
+ 'panose-1': 'panose1',
324
+ pathlength: 'pathLength',
325
+ patterncontentunits: 'patternContentUnits',
326
+ patterntransform: 'patternTransform',
327
+ patternunits: 'patternUnits',
328
+ pointerevents: 'pointerEvents',
329
+ 'pointer-events': 'pointerEvents',
330
+ points: 'points',
331
+ pointsatx: 'pointsAtX',
332
+ pointsaty: 'pointsAtY',
333
+ pointsatz: 'pointsAtZ',
334
+ prefix: 'prefix',
335
+ preservealpha: 'preserveAlpha',
336
+ preserveaspectratio: 'preserveAspectRatio',
337
+ primitiveunits: 'primitiveUnits',
338
+ property: 'property',
339
+ r: 'r',
340
+ radius: 'radius',
341
+ refx: 'refX',
342
+ refy: 'refY',
343
+ renderingintent: 'renderingIntent',
344
+ 'rendering-intent': 'renderingIntent',
345
+ repeatcount: 'repeatCount',
346
+ repeatdur: 'repeatDur',
347
+ requiredextensions: 'requiredExtensions',
348
+ requiredfeatures: 'requiredFeatures',
349
+ resource: 'resource',
350
+ restart: 'restart',
351
+ result: 'result',
352
+ results: 'results',
353
+ rotate: 'rotate',
354
+ rx: 'rx',
355
+ ry: 'ry',
356
+ scale: 'scale',
357
+ security: 'security',
358
+ seed: 'seed',
359
+ shaperendering: 'shapeRendering',
360
+ 'shape-rendering': 'shapeRendering',
361
+ slope: 'slope',
362
+ spacing: 'spacing',
363
+ specularconstant: 'specularConstant',
364
+ specularexponent: 'specularExponent',
365
+ speed: 'speed',
366
+ spreadmethod: 'spreadMethod',
367
+ startoffset: 'startOffset',
368
+ stddeviation: 'stdDeviation',
369
+ stemh: 'stemh',
370
+ stemv: 'stemv',
371
+ stitchtiles: 'stitchTiles',
372
+ stopcolor: 'stopColor',
373
+ 'stop-color': 'stopColor',
374
+ stopopacity: 'stopOpacity',
375
+ 'stop-opacity': 'stopOpacity',
376
+ strikethroughposition: 'strikethroughPosition',
377
+ 'strikethrough-position': 'strikethroughPosition',
378
+ strikethroughthickness: 'strikethroughThickness',
379
+ 'strikethrough-thickness': 'strikethroughThickness',
380
+ string: 'string',
381
+ stroke: 'stroke',
382
+ strokedasharray: 'strokeDasharray',
383
+ 'stroke-dasharray': 'strokeDasharray',
384
+ strokedashoffset: 'strokeDashoffset',
385
+ 'stroke-dashoffset': 'strokeDashoffset',
386
+ strokelinecap: 'strokeLinecap',
387
+ 'stroke-linecap': 'strokeLinecap',
388
+ strokelinejoin: 'strokeLinejoin',
389
+ 'stroke-linejoin': 'strokeLinejoin',
390
+ strokemiterlimit: 'strokeMiterlimit',
391
+ 'stroke-miterlimit': 'strokeMiterlimit',
392
+ strokewidth: 'strokeWidth',
393
+ 'stroke-width': 'strokeWidth',
394
+ strokeopacity: 'strokeOpacity',
395
+ 'stroke-opacity': 'strokeOpacity',
396
+ suppresscontenteditablewarning: 'suppressContentEditableWarning',
397
+ suppresshydrationwarning: 'suppressHydrationWarning',
398
+ surfacescale: 'surfaceScale',
399
+ systemlanguage: 'systemLanguage',
400
+ tablevalues: 'tableValues',
401
+ targetx: 'targetX',
402
+ targety: 'targetY',
403
+ textanchor: 'textAnchor',
404
+ 'text-anchor': 'textAnchor',
405
+ textdecoration: 'textDecoration',
406
+ 'text-decoration': 'textDecoration',
407
+ textlength: 'textLength',
408
+ textrendering: 'textRendering',
409
+ 'text-rendering': 'textRendering',
410
+ to: 'to',
411
+ transform: 'transform',
412
+ typeof: 'typeof',
413
+ u1: 'u1',
414
+ u2: 'u2',
415
+ underlineposition: 'underlinePosition',
416
+ 'underline-position': 'underlinePosition',
417
+ underlinethickness: 'underlineThickness',
418
+ 'underline-thickness': 'underlineThickness',
419
+ unicode: 'unicode',
420
+ unicodebidi: 'unicodeBidi',
421
+ 'unicode-bidi': 'unicodeBidi',
422
+ unicoderange: 'unicodeRange',
423
+ 'unicode-range': 'unicodeRange',
424
+ unitsperem: 'unitsPerEm',
425
+ 'units-per-em': 'unitsPerEm',
426
+ unselectable: 'unselectable',
427
+ valphabetic: 'vAlphabetic',
428
+ 'v-alphabetic': 'vAlphabetic',
429
+ values: 'values',
430
+ vectoreffect: 'vectorEffect',
431
+ 'vector-effect': 'vectorEffect',
432
+ version: 'version',
433
+ vertadvy: 'vertAdvY',
434
+ 'vert-adv-y': 'vertAdvY',
435
+ vertoriginx: 'vertOriginX',
436
+ 'vert-origin-x': 'vertOriginX',
437
+ vertoriginy: 'vertOriginY',
438
+ 'vert-origin-y': 'vertOriginY',
439
+ vhanging: 'vHanging',
440
+ 'v-hanging': 'vHanging',
441
+ videographic: 'vIdeographic',
442
+ 'v-ideographic': 'vIdeographic',
443
+ viewbox: 'viewBox',
444
+ viewtarget: 'viewTarget',
445
+ visibility: 'visibility',
446
+ vmathematical: 'vMathematical',
447
+ 'v-mathematical': 'vMathematical',
448
+ vocab: 'vocab',
449
+ widths: 'widths',
450
+ wordspacing: 'wordSpacing',
451
+ 'word-spacing': 'wordSpacing',
452
+ writingmode: 'writingMode',
453
+ 'writing-mode': 'writingMode',
454
+ x1: 'x1',
455
+ x2: 'x2',
456
+ x: 'x',
457
+ xchannelselector: 'xChannelSelector',
458
+ xheight: 'xHeight',
459
+ 'x-height': 'xHeight',
460
+ xlinkactuate: 'xlinkActuate',
461
+ 'xlink:actuate': 'xlinkActuate',
462
+ xlinkarcrole: 'xlinkArcrole',
463
+ 'xlink:arcrole': 'xlinkArcrole',
464
+ xlinkhref: 'xlinkHref',
465
+ 'xlink:href': 'xlinkHref',
466
+ xlinkrole: 'xlinkRole',
467
+ 'xlink:role': 'xlinkRole',
468
+ xlinkshow: 'xlinkShow',
469
+ 'xlink:show': 'xlinkShow',
470
+ xlinktitle: 'xlinkTitle',
471
+ 'xlink:title': 'xlinkTitle',
472
+ xlinktype: 'xlinkType',
473
+ 'xlink:type': 'xlinkType',
474
+ xmlbase: 'xmlBase',
475
+ 'xml:base': 'xmlBase',
476
+ xmllang: 'xmlLang',
477
+ 'xml:lang': 'xmlLang',
478
+ xmlns: 'xmlns',
479
+ 'xml:space': 'xmlSpace',
480
+ xmlnsxlink: 'xmlnsXlink',
481
+ 'xmlns:xlink': 'xmlnsXlink',
482
+ xmlspace: 'xmlSpace',
483
+ y1: 'y1',
484
+ y2: 'y2',
485
+ y: 'y',
486
+ ychannelselector: 'yChannelSelector',
487
+ z: 'z',
488
+ zoomandpan: 'zoomAndPan'
489
+ }
490
+
491
+ def redirect_back_with_props_at(opts)
492
+ if request.referrer && params[:props_at]
493
+ referrer_url = URI.parse(request.referrer)
494
+ referrer_url.query = Rack::Utils
495
+ .parse_nested_query(referrer_url.query)
496
+ .merge({props_at: params[:props_at]})
497
+ .to_query
498
+
499
+ redirect_to referrer_url.to_s, opts
500
+ else
501
+ redirect_back(opts)
502
+ end
503
+ end
504
+
505
+ def props_from_form_with(model: nil, scope: nil, url: nil, format: nil, **options)
506
+ options[:allow_method_names_outside_object] = true
507
+ options[:skip_default_ids] = !helpers.send(:form_with_generates_ids)
508
+
509
+ if model
510
+ url ||= helpers.send(:polymorphic_path, model, format: format)
511
+
512
+ model = model.last if model.is_a?(Array)
513
+ scope ||= helpers.send(:model_name_from_record_or_class, model).param_key
514
+ end
515
+
516
+ html_options = helpers.send(:html_options_for_form_with, url, model, options)
517
+ html_options.delete("authenticity_token")
518
+ html_options.delete("enforce_utf8")
519
+
520
+ key_vals = html_options.map { |k, v|
521
+ [POSSIBLE_STANDARD_NAMES[k.to_sym] || k.camelize(:lower), v]
522
+ }
523
+ Hash[key_vals]
524
+ end
525
+
526
+ def param_to_search_path(param)
527
+ if param
528
+ param.gsub(/[^\da-zA-Z\_\=\.]+/, '')
529
+ .gsub(/\.+/, '.')
530
+ .split('.')
531
+ .map do |part|
532
+ if part =~ /^-?[0-9]+$/
533
+ part.to_i
534
+ else
535
+ part
536
+ end
537
+ end
538
+ end
539
+ end
540
+
541
+ def search_path_to_camelized_param(path)
542
+ path.map do |part|
543
+ if part.include? '='
544
+ key, rest = part.split('=')
545
+ [key.camelize(:lower), rest].join('=')
546
+ else
547
+ part.camelize(:lower)
548
+ end
549
+ end.join('.')
550
+ end
551
+ end
552
+ end