webring-rails 1.5.0 → 1.7.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.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/app/assets/javascripts/webring/widget.js +66 -24
- data/app/assets/javascripts/webring/widget.min.js +1 -1
- data/app/controllers/webring/members_controller.rb +1 -1
- data/app/controllers/webring/navigation_controller.rb +2 -0
- data/app/controllers/webring/widget_controller.rb +7 -8
- data/app/models/concerns/webring/membership_request_actions.rb +1 -0
- data/lib/generators/webring/member/templates/migration.rb +2 -1
- data/lib/generators/webring/navigation_controller/templates/navigation_controller.rb +2 -0
- data/lib/webring/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 85a5b42e96746928c014435c11237eace0ad0219f0dda1ef94c682d4659ff821
|
4
|
+
data.tar.gz: 5cae67399d29d43add826956e4f061bf646364c25bfa02c94ea2c4b82ac74d16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a83df3a9470ec0612cdf66b649fb500e3167a191b709455792fa98c88b68711233f906263dc6e345cd86d042219b79b90a24cd4be96a061887d0f2a8d210a2e2
|
7
|
+
data.tar.gz: 563281f534ced604e59d885771c9ca828a42c416b23b6aa4809ff1bdba1b3a40a7bb329808a7bbe707834923785b078ce85696922581ac9ec6aed42fd83aac6c
|
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
# Webring for Rails
|
4
4
|
|
5
|
+
[](https://badge.fury.io/rb/webring-rails)
|
6
|
+
|
5
7
|
[Webring for Rails (webring-rails)](https://github.com/cybergizer-hq/webring-rails) is a flexible engine for creating and managing a webring system in your Ruby on Rails application. A webring is a collection of websites linked together in a circular structure, allowing visitors to navigate from one site to another.
|
6
8
|
|
7
9
|
## Features
|
@@ -22,6 +22,7 @@
|
|
22
22
|
* - full: Apply all styles (default)
|
23
23
|
* - layout: Only layout styles, no visual design
|
24
24
|
* - none: No styles applied
|
25
|
+
* - data-theme="light|dark": Sets the theme for the widget. Default: light
|
25
26
|
* - data-prev-text="Custom Text": Sets custom text for the "previous" button. Default: "« Prev"
|
26
27
|
* - data-random-text="Custom Text": Sets custom text for the "random" button (keeps the logo). Default: "Random"
|
27
28
|
* - data-next-text="Custom Text": Sets custom text for the "next" button. Default: "Next »"
|
@@ -36,7 +37,9 @@
|
|
36
37
|
DEFAULT_TARGET_ID: 'webring-widget',
|
37
38
|
STYLE_ID: 'webring-widget-styles',
|
38
39
|
VALID_STYLE_TYPES: Object.freeze(['full', 'layout', 'none']),
|
39
|
-
DEFAULT_STYLE_TYPE: 'full'
|
40
|
+
DEFAULT_STYLE_TYPE: 'full',
|
41
|
+
VALID_THEMES: Object.freeze(['light', 'dark']),
|
42
|
+
DEFAULT_THEME: 'light'
|
40
43
|
});
|
41
44
|
|
42
45
|
// Default text configurations
|
@@ -204,8 +207,7 @@
|
|
204
207
|
box-sizing: border-box;
|
205
208
|
}
|
206
209
|
.webring-nav .webring-title {
|
207
|
-
margin
|
208
|
-
margin-top: 0;
|
210
|
+
margin: 0 0 8px 0;
|
209
211
|
padding: 0;
|
210
212
|
font-size: inherit;
|
211
213
|
line-height: normal;
|
@@ -245,48 +247,84 @@
|
|
245
247
|
.webring-nav .webring-logo-inline {
|
246
248
|
display: inline-block;
|
247
249
|
vertical-align: middle;
|
248
|
-
margin
|
249
|
-
margin-top: 1px;
|
250
|
-
margin-bottom: 0;
|
251
|
-
margin-left: 0;
|
250
|
+
margin: 1px 6px 0 0;
|
252
251
|
}
|
253
252
|
.webring-nav[data-button-text="false"] .prev-btn {
|
254
|
-
padding
|
255
|
-
padding-right: 12.5px;
|
253
|
+
padding: 5px 12.5px 6px 12px;
|
256
254
|
}
|
257
255
|
.webring-nav[data-button-text="false"] .next-btn {
|
258
|
-
padding
|
259
|
-
padding-left: 12.5px;
|
256
|
+
padding: 5px 12px 6px 12.5px;
|
260
257
|
}
|
261
258
|
`,
|
262
259
|
design: `
|
260
|
+
/* CSS Custom Properties for easy theming */
|
261
|
+
.webring-nav {
|
262
|
+
/* Internal variables that use public API with fallbacks */
|
263
|
+
--webring-bg-color: var(--webring-theme-bg);
|
264
|
+
--webring-border-color: var(--webring-theme-border);
|
265
|
+
--webring-text-color: var(--webring-theme-text);
|
266
|
+
--webring-btn-bg: var(--webring-theme-btn-bg);
|
267
|
+
--webring-btn-border: var(--webring-theme-btn-border);
|
268
|
+
--webring-btn-text: var(--webring-theme-btn-text);
|
269
|
+
--webring-btn-hover-bg: var(--webring-theme-btn-hover-bg);
|
270
|
+
--webring-btn-hover-text: var(--webring-theme-btn-hover-text);
|
271
|
+
}
|
272
|
+
|
273
|
+
/* Common theme styles using CSS variables */
|
274
|
+
.webring-nav {
|
275
|
+
background-color: var(--webring-bg-color);
|
276
|
+
}
|
263
277
|
.webring-nav[data-widget-type="full"] {
|
264
|
-
border: 2.5px solid
|
278
|
+
border: 2.5px solid var(--webring-border-color);
|
265
279
|
}
|
266
280
|
.webring-nav .webring-title {
|
267
281
|
font-weight: 600;
|
282
|
+
color: var(--webring-text-color);
|
268
283
|
}
|
269
284
|
.webring-nav .webring-btn {
|
270
285
|
text-wrap: nowrap;
|
271
|
-
color: #000000;
|
272
286
|
font-weight: 600;
|
273
|
-
|
274
|
-
|
287
|
+
color: var(--webring-btn-text);
|
288
|
+
background-color: var(--webring-btn-bg);
|
289
|
+
border: 2.5px solid var(--webring-btn-border);
|
275
290
|
transition: background-color 0.2s ease, color 0.2s ease;
|
276
291
|
}
|
277
|
-
.webring-nav .webring-btn:hover {
|
278
|
-
background-color: #000000;
|
279
|
-
color: #ffffff;
|
280
|
-
}
|
281
292
|
.webring-nav .webring-btn:focus {
|
282
293
|
outline: none;
|
283
294
|
background-color: transparent;
|
284
|
-
color:
|
295
|
+
color: var(--webring-btn-text);
|
285
296
|
}
|
297
|
+
.webring-nav .webring-btn:hover,
|
286
298
|
.webring-nav .webring-btn:active {
|
287
|
-
|
288
|
-
|
289
|
-
|
299
|
+
background-color: var(--webring-btn-hover-bg);
|
300
|
+
color: var(--webring-btn-hover-text);
|
301
|
+
}
|
302
|
+
.webring-nav svg {
|
303
|
+
fill: currentColor;
|
304
|
+
}
|
305
|
+
|
306
|
+
/* Light theme defaults - these have lower specificity than member's rules */
|
307
|
+
.webring-nav {
|
308
|
+
--webring-theme-bg: #ffffff;
|
309
|
+
--webring-theme-border: #000000;
|
310
|
+
--webring-theme-text: #000000;
|
311
|
+
--webring-theme-btn-bg: #ffffff;
|
312
|
+
--webring-theme-btn-border: #000000;
|
313
|
+
--webring-theme-btn-text: #000000;
|
314
|
+
--webring-theme-btn-hover-bg: #000000;
|
315
|
+
--webring-theme-btn-hover-text: #ffffff;
|
316
|
+
}
|
317
|
+
|
318
|
+
/* Dark theme overrides */
|
319
|
+
.webring-nav[data-theme="dark"] {
|
320
|
+
--webring-theme-bg: #000000;
|
321
|
+
--webring-theme-border: #ffffff;
|
322
|
+
--webring-theme-text: #ffffff;
|
323
|
+
--webring-theme-btn-bg: #000000;
|
324
|
+
--webring-theme-btn-border: #ffffff;
|
325
|
+
--webring-theme-btn-text: #ffffff;
|
326
|
+
--webring-theme-btn-hover-bg: #ffffff;
|
327
|
+
--webring-theme-btn-hover-text: #000000;
|
290
328
|
}
|
291
329
|
`
|
292
330
|
});
|
@@ -310,6 +348,8 @@
|
|
310
348
|
const buttonText = script.getAttribute('data-button-text') !== 'false';
|
311
349
|
const stylesType = script.getAttribute('data-styles') ?? WIDGET_CONFIG.DEFAULT_STYLE_TYPE;
|
312
350
|
const stylesOption = WIDGET_CONFIG.VALID_STYLE_TYPES.includes(stylesType) ? stylesType : WIDGET_CONFIG.DEFAULT_STYLE_TYPE;
|
351
|
+
const themeType = script.getAttribute('data-theme') ?? WIDGET_CONFIG.DEFAULT_THEME;
|
352
|
+
const theme = WIDGET_CONFIG.VALID_THEMES.includes(themeType) ? themeType : WIDGET_CONFIG.DEFAULT_THEME;
|
313
353
|
|
314
354
|
// Custom text data attributes
|
315
355
|
const prevText = script.getAttribute('data-prev-text');
|
@@ -351,6 +391,7 @@
|
|
351
391
|
wrapperDiv.className = 'webring-nav';
|
352
392
|
wrapperDiv.setAttribute('data-widget-type', widgetType);
|
353
393
|
wrapperDiv.setAttribute('data-button-text', buttonText.toString());
|
394
|
+
wrapperDiv.setAttribute('data-theme', theme);
|
354
395
|
|
355
396
|
// Apply custom texts efficiently
|
356
397
|
const customTexts = {
|
@@ -427,7 +468,8 @@
|
|
427
468
|
if (!styleElement) {
|
428
469
|
styleElement = document.createElement('style');
|
429
470
|
styleElement.id = WIDGET_CONFIG.STYLE_ID;
|
430
|
-
|
471
|
+
// Insert at the beginning of head so user styles can override
|
472
|
+
document.head.insertBefore(styleElement, document.head.firstChild);
|
431
473
|
}
|
432
474
|
|
433
475
|
switch (styleOption) {
|
@@ -1 +1 @@
|
|
1
|
-
!function(){function n(n){function t(n){let t=document.getElementById(e.STYLE_ID);switch(t||(t=document.createElement("style"),t.id=e.STYLE_ID,document.head.appendChild(t)),n){case"none":t.textContent=g.reset;break;case"layout":t.textContent=g.reset+g.layout;break;default:t.textContent=g.reset+g.layout+g.design}}const i=n||document.currentScript||document.getElementsByTagName("script")[document.getElementsByTagName("script").length-1];if(!i)return;const a=i.getAttribute("data-member-uid"),b=i.getAttribute("data-widget-type")??e.DEFAULT_TYPE,c=i.getAttribute("data-target-id")??e.DEFAULT_TARGET_ID,p="false"!==i.getAttribute("data-button-text"),f=i.getAttribute("data-styles")??e.DEFAULT_STYLE_TYPE,w=e.VALID_STYLE_TYPES.includes(f)?f:e.DEFAULT_STYLE_TYPE,m=i.getAttribute("data-prev-text"),u=i.getAttribute("data-random-text"),x=i.getAttribute("data-next-text"),v=i.getAttribute("data-widget-text");if(!a)return void console.error("Webring Widget: Missing data-member-uid attribute on script tag.");if(!e.VALID_TYPES.includes(b))return void console.error(`Webring Widget: Invalid widget type "${b}". Valid types: ${e.VALID_TYPES.join(", ")}`);const h=i.getAttribute("src"),y=new URL(h,window.location.href).origin,T=function(){const n=document.getElementById(c);if(!n)return void console.error(`Webring Widget: No element with id "${c}" found.`);s||(t(w),s=!0);const e=document.createDocumentFragment(),i=document.createElement("div");i.className="webring-nav",i.setAttribute("data-widget-type",b),i.setAttribute("data-button-text",p.toString());const g={prev:d.prev.text_enforced?d.prev:m?{...d.prev,text:`\xab ${m}`}:d.prev,random:d.random.text_enforced?d.random:u?{...d.random,text:`${r(20,20,"margin-right: 4px; margin-top: 1px;")} ${u}`}:d.random,next:d.next.text_enforced?d.next:x?{...d.next,text:`${x} \xbb`}:d.next,logoOnly:d.logoOnly},f=l[b];if(f.showTitle){const n=document.createElement("span");n.className="webring-title",n.innerHTML=o.widgetTitle.enforced?o.widgetTitle.default:v??o.widgetTitle.default,i.appendChild(n)}const h=document.createElement("nav");h.className="webring-buttons",f.actions.forEach((n=>{const e=g[n];if("logoOnly"===n){const n=document.createElement("div");return n.className=e.additionalClass,n.innerHTML=e.symbol,void h.appendChild(n)}const t=document.createElement("a");if(t.href=`${y}/webring/${e.path}?source_member_uid=${a}`,t.title=e.title,t.className=`webring-btn ${e.additionalClass}`,"one-way"===b&&f.showLogoInButton&&"next"===n){const n=d.next.text_enforced?o.next.default:x||g.next.text.replace(" \xbb","");t.innerHTML=p?`<span class="webring-logo-inline">${r(20,20)}</span> ${n} \xbb`:`<span class="webring-logo-inline">${r(20,20)}</span> ${e.symbol}`}else t.innerHTML=p?e.text:e.symbol;h.appendChild(t)})),i.appendChild(h),e.appendChild(i),n.innerHTML="",n.appendChild(e)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",T):T()}const e=Object.freeze({VALID_TYPES:Object.freeze(["full","no-text","two-way","one-way","random-only"]),DEFAULT_TYPE:"full",DEFAULT_TARGET_ID:"webring-widget",STYLE_ID:"webring-widget-styles",VALID_STYLE_TYPES:Object.freeze(["full","layout","none"]),DEFAULT_STYLE_TYPE:"full"}),t=Object.freeze({prev:{default:"\xab Prev",enforced:!1},random:{default:"Random",enforced:!1},next:{default:"Next \xbb",enforced:!1},widgetTitle:{default:"Webring",enforced:!1}}),i="<<REPLACE_ME_TEXT_DEFAULTS>>",a="<<REPLACE_ME_TEXT_DEFAULTS>>"!==i?"string"==typeof i?JSON.parse(i):i:{},o=Object.freeze(Object.keys(t).reduce(((n,e)=>{const i=a[e];return n[e]={default:i?.default??t[e].default,enforced:i?.enforced??t[e].enforced},n}),{})),r="<<REPLACE_ME_LOGO_SVG_FUNCTION>>",d=Object.freeze({prev:{symbol:"\xab",text:`\xab ${o.prev.default}`,text_enforced:o.prev.enforced,title:"Previous site",path:"previous",additionalClass:"prev-btn"},random:{symbol:r(23,23),text:`${r(20,20,"margin-right: 4px; margin-top: 1px;")} ${o.random.default}`,text_enforced:o.random.enforced,title:"Random site",path:"random",additionalClass:"random-btn"},next:{symbol:"\xbb",text:`${o.next.default} \xbb`,text_enforced:o.next.enforced,title:"Next site",path:"next",additionalClass:"next-btn"},logoOnly:{symbol:r(23,23),text:r(23,23),path:"",additionalClass:"logo-only"}}),l=Object.freeze({full:{showTitle:!0,actions:["prev","random","next"]},"no-text":{showTitle:!1,actions:["prev","random","next"]},"two-way":{showTitle:!1,actions:["prev","logoOnly","next"],showLogoInMiddle:!0},"one-way":{showTitle:!1,actions:["next"],showLogoInButton:!0},"random-only":{showTitle:!1,actions:["random"]}}),g=Object.freeze({reset:"\n .webring-nav,\n .webring-nav div,\n .webring-nav span,\n .webring-nav nav,\n .webring-nav a,\n .webring-nav div::before,\n .webring-nav span::before,\n .webring-nav nav::before,\n .webring-nav a::before,\n .webring-nav div::after,\n .webring-nav span::after,\n .webring-nav nav::after,\n .webring-nav a::after {\n all: initial;\n box-sizing: border-box;\n }\n\n // .webring-nav svg,\n // .webring-nav svg * {\n // all: revert;\n // fill: currentColor;\n // }\n\n .webring-nav,\n .webring-nav div,\n .webring-nav span,\n .webring-nav nav,\n .webring-nav a {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n color: inherit;\n }\n\n .webring-nav div,\n .webring-nav span,\n .webring-nav nav,\n .webring-nav a {\n display: initial;\n margin: 0;\n padding: 0;\n border: none;\n background: none;\n text-decoration: none;\n color: inherit;\n font-weight: inherit;\n font-size: inherit;\n line-height: inherit;\n vertical-align: baseline;\n box-shadow: none;\n outline: none;\n transform: none;\n opacity: 1;\n visibility: visible;\n position: static;\n float: none;\n clear: none;\n overflow: visible;\n white-space: normal;\n text-align: left;\n letter-spacing: normal;\n word-spacing: normal;\n text-transform: none;\n text-shadow: none;\n list-style: none;\n border-radius: 0;\n min-width: auto;\n max-width: none;\n min-height: auto;\n max-height: none;\n width: auto;\n height: auto;\n top: auto;\n right: auto;\n bottom: auto;\n left: auto;\n z-index: auto;\n }\n\n .webring-nav a {\n cursor: pointer;\n }\n ",layout:'\n .webring-nav {\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;\n font-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: center;\n max-width: 350px;\n margin: 0 auto;\n padding: 10px;\n box-sizing: border-box;\n }\n .webring-nav .webring-title {\n margin-bottom: 8px;\n margin-top: 0;\n padding: 0;\n font-size: inherit;\n line-height: normal;\n }\n .webring-nav nav {\n display: flex;\n gap: 10px;\n width: 100%;\n justify-content: center;\n align-items: center;\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n .webring-nav .webring-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px 12px;\n text-decoration: none;\n box-sizing: border-box;\n margin: 0;\n }\n .webring-nav .webring-btn.random-btn {\n padding: 6px 8px;\n }\n .webring-nav nav .logo-only {\n padding: 8px 3px 6px 3px;\n margin: 0;\n }\n .webring-nav[data-widget-type="no-text"] {\n padding: 8px 10px;\n }\n .webring-nav[data-widget-type="one-way"] {\n max-width: 200px;\n }\n .webring-nav .webring-logo-inline {\n display: inline-block;\n vertical-align: middle;\n margin-right: 6px;\n margin-top: 1px;\n margin-bottom: 0;\n margin-left: 0;\n }\n .webring-nav[data-button-text="false"] .prev-btn {\n padding-top: 5px;\n padding-right: 12.5px;\n }\n .webring-nav[data-button-text="false"] .next-btn {\n padding-top: 5px;\n padding-left: 12.5px;\n }\n ',design:'\n .webring-nav[data-widget-type="full"] {\n border: 2.5px solid #000000;\n }\n .webring-nav .webring-title {\n font-weight: 600;\n }\n .webring-nav .webring-btn {\n text-wrap: nowrap;\n color: #000000;\n font-weight: 600;\n background-color: #ffffff;\n border: 2.5px solid #000000;\n transition: background-color 0.2s ease, color 0.2s ease;\n }\n .webring-nav .webring-btn:hover {\n background-color: #000000;\n color: #ffffff;\n }\n .webring-nav .webring-btn:focus {\n outline: none;\n background-color: transparent;\n color: #000000;\n }\n .webring-nav .webring-btn:active {\n border-color: #000000;\n background-color: #000000;\n color: #ffffff;\n }\n '});let s=!1;n()}();
|
1
|
+
!function(){function n(n){function t(n){let t=document.getElementById(e.STYLE_ID);switch(t||(t=document.createElement("style"),t.id=e.STYLE_ID,document.head.insertBefore(t,document.head.firstChild)),n){case"none":t.textContent=g.reset;break;case"layout":t.textContent=g.reset+g.layout;break;default:t.textContent=g.reset+g.layout+g.design}}const r=n||document.currentScript||document.getElementsByTagName("script")[document.getElementsByTagName("script").length-1];if(!r)return;const i=r.getAttribute("data-member-uid"),s=r.getAttribute("data-widget-type")??e.DEFAULT_TYPE,c=r.getAttribute("data-target-id")??e.DEFAULT_TARGET_ID,w="false"!==r.getAttribute("data-button-text"),f=r.getAttribute("data-styles")??e.DEFAULT_STYLE_TYPE,m=e.VALID_STYLE_TYPES.includes(f)?f:e.DEFAULT_STYLE_TYPE,v=r.getAttribute("data-theme")??e.DEFAULT_THEME,x=e.VALID_THEMES.includes(v)?v:e.DEFAULT_THEME,p=r.getAttribute("data-prev-text"),u=r.getAttribute("data-random-text"),h=r.getAttribute("data-next-text"),E=r.getAttribute("data-widget-text");if(!i)return void console.error("Webring Widget: Missing data-member-uid attribute on script tag.");if(!e.VALID_TYPES.includes(s))return void console.error(`Webring Widget: Invalid widget type "${s}". Valid types: ${e.VALID_TYPES.join(", ")}`);const y=r.getAttribute("src"),T=new URL(y,window.location.href).origin,_=function(){const n=document.getElementById(c);if(!n)return void console.error(`Webring Widget: No element with id "${c}" found.`);l||(t(m),l=!0);const e=document.createDocumentFragment(),r=document.createElement("div");r.className="webring-nav",r.setAttribute("data-widget-type",s),r.setAttribute("data-button-text",w.toString()),r.setAttribute("data-theme",x);const g={prev:b.prev.text_enforced?b.prev:p?{...b.prev,text:`\xab ${p}`}:b.prev,random:b.random.text_enforced?b.random:u?{...b.random,text:`${o(20,20,"margin-right: 4px; margin-top: 1px;")} ${u}`}:b.random,next:b.next.text_enforced?b.next:h?{...b.next,text:`${h} \xbb`}:b.next,logoOnly:b.logoOnly},f=d[s];if(f.showTitle){const n=document.createElement("span");n.className="webring-title",n.innerHTML=a.widgetTitle.enforced?a.widgetTitle.default:E??a.widgetTitle.default,r.appendChild(n)}const v=document.createElement("nav");v.className="webring-buttons",f.actions.forEach((n=>{const e=g[n];if("logoOnly"===n){const n=document.createElement("div");return n.className=e.additionalClass,n.innerHTML=e.symbol,void v.appendChild(n)}const t=document.createElement("a");if(t.href=`${T}/webring/${e.path}?source_member_uid=${i}`,t.title=e.title,t.className=`webring-btn ${e.additionalClass}`,"one-way"===s&&f.showLogoInButton&&"next"===n){const n=b.next.text_enforced?a.next.default:h||g.next.text.replace(" \xbb","");t.innerHTML=w?`<span class="webring-logo-inline">${o(20,20)}</span> ${n} \xbb`:`<span class="webring-logo-inline">${o(20,20)}</span> ${e.symbol}`}else t.innerHTML=w?e.text:e.symbol;v.appendChild(t)})),r.appendChild(v),e.appendChild(r),n.innerHTML="",n.appendChild(e)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",_):_()}const e=Object.freeze({VALID_TYPES:Object.freeze(["full","no-text","two-way","one-way","random-only"]),DEFAULT_TYPE:"full",DEFAULT_TARGET_ID:"webring-widget",STYLE_ID:"webring-widget-styles",VALID_STYLE_TYPES:Object.freeze(["full","layout","none"]),DEFAULT_STYLE_TYPE:"full",VALID_THEMES:Object.freeze(["light","dark"]),DEFAULT_THEME:"light"}),t=Object.freeze({prev:{default:"\xab Prev",enforced:!1},random:{default:"Random",enforced:!1},next:{default:"Next \xbb",enforced:!1},widgetTitle:{default:"Webring",enforced:!1}}),r="<<REPLACE_ME_TEXT_DEFAULTS>>",i="<<REPLACE_ME_TEXT_DEFAULTS>>"!==r?"string"==typeof r?JSON.parse(r):r:{},a=Object.freeze(Object.keys(t).reduce(((n,e)=>{const r=i[e];return n[e]={default:r?.default??t[e].default,enforced:r?.enforced??t[e].enforced},n}),{})),o="<<REPLACE_ME_LOGO_SVG_FUNCTION>>",b=Object.freeze({prev:{symbol:"\xab",text:`\xab ${a.prev.default}`,text_enforced:a.prev.enforced,title:"Previous site",path:"previous",additionalClass:"prev-btn"},random:{symbol:o(23,23),text:`${o(20,20,"margin-right: 4px; margin-top: 1px;")} ${a.random.default}`,text_enforced:a.random.enforced,title:"Random site",path:"random",additionalClass:"random-btn"},next:{symbol:"\xbb",text:`${a.next.default} \xbb`,text_enforced:a.next.enforced,title:"Next site",path:"next",additionalClass:"next-btn"},logoOnly:{symbol:o(23,23),text:o(23,23),path:"",additionalClass:"logo-only"}}),d=Object.freeze({full:{showTitle:!0,actions:["prev","random","next"]},"no-text":{showTitle:!1,actions:["prev","random","next"]},"two-way":{showTitle:!1,actions:["prev","logoOnly","next"],showLogoInMiddle:!0},"one-way":{showTitle:!1,actions:["next"],showLogoInButton:!0},"random-only":{showTitle:!1,actions:["random"]}}),g=Object.freeze({reset:"\n .webring-nav,\n .webring-nav div,\n .webring-nav span,\n .webring-nav nav,\n .webring-nav a,\n .webring-nav div::before,\n .webring-nav span::before,\n .webring-nav nav::before,\n .webring-nav a::before,\n .webring-nav div::after,\n .webring-nav span::after,\n .webring-nav nav::after,\n .webring-nav a::after {\n all: initial;\n box-sizing: border-box;\n }\n\n .webring-nav,\n .webring-nav div,\n .webring-nav span,\n .webring-nav nav,\n .webring-nav a {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n color: inherit;\n }\n\n .webring-nav div,\n .webring-nav span,\n .webring-nav nav,\n .webring-nav a {\n display: initial;\n margin: 0;\n padding: 0;\n border: none;\n background: none;\n text-decoration: none;\n color: inherit;\n font-weight: inherit;\n font-size: inherit;\n line-height: inherit;\n vertical-align: baseline;\n box-shadow: none;\n outline: none;\n transform: none;\n opacity: 1;\n visibility: visible;\n position: static;\n float: none;\n clear: none;\n overflow: visible;\n white-space: normal;\n text-align: left;\n letter-spacing: normal;\n word-spacing: normal;\n text-transform: none;\n text-shadow: none;\n list-style: none;\n border-radius: 0;\n min-width: auto;\n max-width: none;\n min-height: auto;\n max-height: none;\n width: auto;\n height: auto;\n top: auto;\n right: auto;\n bottom: auto;\n left: auto;\n z-index: auto;\n }\n\n .webring-nav a {\n cursor: pointer;\n }\n ",layout:'\n .webring-nav {\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;\n font-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: center;\n max-width: 350px;\n margin: 0 auto;\n padding: 10px;\n box-sizing: border-box;\n }\n .webring-nav .webring-title {\n margin: 0 0 8px 0;\n padding: 0;\n font-size: inherit;\n line-height: normal;\n }\n .webring-nav nav {\n display: flex;\n gap: 10px;\n width: 100%;\n justify-content: center;\n align-items: center;\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n .webring-nav .webring-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px 12px;\n text-decoration: none;\n box-sizing: border-box;\n margin: 0;\n }\n .webring-nav .webring-btn.random-btn {\n padding: 6px 8px;\n }\n .webring-nav nav .logo-only {\n padding: 8px 3px 6px 3px;\n margin: 0;\n }\n .webring-nav[data-widget-type="no-text"] {\n padding: 8px 10px;\n }\n .webring-nav[data-widget-type="one-way"] {\n max-width: 200px;\n }\n .webring-nav .webring-logo-inline {\n display: inline-block;\n vertical-align: middle;\n margin: 1px 6px 0 0;\n }\n .webring-nav[data-button-text="false"] .prev-btn {\n padding: 5px 12.5px 6px 12px;\n }\n .webring-nav[data-button-text="false"] .next-btn {\n padding: 5px 12px 6px 12.5px;\n }\n ',design:'\n /* CSS Custom Properties for easy theming */\n .webring-nav {\n /* Internal variables that use public API with fallbacks */\n --webring-bg-color: var(--webring-theme-bg);\n --webring-border-color: var(--webring-theme-border);\n --webring-text-color: var(--webring-theme-text);\n --webring-btn-bg: var(--webring-theme-btn-bg);\n --webring-btn-border: var(--webring-theme-btn-border);\n --webring-btn-text: var(--webring-theme-btn-text);\n --webring-btn-hover-bg: var(--webring-theme-btn-hover-bg);\n --webring-btn-hover-text: var(--webring-theme-btn-hover-text);\n }\n\n /* Common theme styles using CSS variables */\n .webring-nav {\n background-color: var(--webring-bg-color);\n }\n .webring-nav[data-widget-type="full"] {\n border: 2.5px solid var(--webring-border-color);\n }\n .webring-nav .webring-title {\n font-weight: 600;\n color: var(--webring-text-color);\n }\n .webring-nav .webring-btn {\n text-wrap: nowrap;\n font-weight: 600;\n color: var(--webring-btn-text);\n background-color: var(--webring-btn-bg);\n border: 2.5px solid var(--webring-btn-border);\n transition: background-color 0.2s ease, color 0.2s ease;\n }\n .webring-nav .webring-btn:focus {\n outline: none;\n background-color: transparent;\n color: var(--webring-btn-text);\n }\n .webring-nav .webring-btn:hover,\n .webring-nav .webring-btn:active {\n background-color: var(--webring-btn-hover-bg);\n color: var(--webring-btn-hover-text);\n }\n .webring-nav svg {\n fill: currentColor;\n }\n\n /* Light theme defaults - these have lower specificity than member\'s rules */\n .webring-nav {\n --webring-theme-bg: #ffffff;\n --webring-theme-border: #000000;\n --webring-theme-text: #000000;\n --webring-theme-btn-bg: #ffffff;\n --webring-theme-btn-border: #000000;\n --webring-theme-btn-text: #000000;\n --webring-theme-btn-hover-bg: #000000;\n --webring-theme-btn-hover-text: #ffffff;\n }\n\n /* Dark theme overrides */\n .webring-nav[data-theme="dark"] {\n --webring-theme-bg: #000000;\n --webring-theme-border: #ffffff;\n --webring-theme-text: #ffffff;\n --webring-theme-btn-bg: #000000;\n --webring-theme-btn-border: #ffffff;\n --webring-theme-btn-text: #ffffff;\n --webring-theme-btn-hover-bg: #ffffff;\n --webring-theme-btn-hover-text: #000000;\n }\n '});let l=!1;n()}();
|
@@ -3,7 +3,6 @@ module Webring
|
|
3
3
|
# Disable CSRF protection for widget.js as it needs to be loaded from other domains
|
4
4
|
skip_forgery_protection
|
5
5
|
|
6
|
-
# Set CORS headers for the widget
|
7
6
|
before_action :set_cors_headers
|
8
7
|
|
9
8
|
# Serve the webring navigation widget JavaScript
|
@@ -28,13 +27,6 @@ module Webring
|
|
28
27
|
|
29
28
|
private
|
30
29
|
|
31
|
-
def set_cors_headers
|
32
|
-
response.headers['Access-Control-Allow-Origin'] = '*'
|
33
|
-
response.headers['Access-Control-Allow-Methods'] = 'GET, OPTIONS'
|
34
|
-
response.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept'
|
35
|
-
response.headers['Access-Control-Max-Age'] = '86400'
|
36
|
-
end
|
37
|
-
|
38
30
|
# This function is used to generate the logo SVG function for the compiled widget.js file to overcome args names compression issue
|
39
31
|
def logo_svg_function
|
40
32
|
<<~JS
|
@@ -57,5 +49,12 @@ module Webring
|
|
57
49
|
widgetTitle: { default: 'Webring', enforced: false }
|
58
50
|
}
|
59
51
|
end
|
52
|
+
|
53
|
+
def set_cors_headers
|
54
|
+
response.headers['Access-Control-Allow-Origin'] = '*'
|
55
|
+
response.headers['Access-Control-Allow-Methods'] = 'GET, OPTIONS'
|
56
|
+
response.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept'
|
57
|
+
response.headers['Access-Control-Max-Age'] = '86400'
|
58
|
+
end
|
60
59
|
end
|
61
60
|
end
|
@@ -4,7 +4,8 @@ class CreateWebringMembers < ActiveRecord::Migration<%= "[#{Rails::VERSION::MAJO
|
|
4
4
|
t.string :uid, null: false, limit: 32
|
5
5
|
t.string :name, null: false
|
6
6
|
t.string :url, null: false
|
7
|
-
t.
|
7
|
+
t.string :owner_email
|
8
|
+
t.text :description
|
8
9
|
t.integer :status, null: false, default: 0
|
9
10
|
|
10
11
|
t.index :uid, unique: true
|
data/lib/webring/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webring-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nikita Shkoda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-06-
|
11
|
+
date: 2025-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|