Quellcode durchsuchen

Move slugify/urlify to discrete utils & remove usage of window.unicodeSlugsEnabled

LB Johnston vor 1 Jahr
Ursprung
Commit
12997b6e15

+ 4 - 3
client/src/controllers/SlugController.ts

@@ -1,5 +1,6 @@
 import { Controller } from '@hotwired/stimulus';
-import { cleanForSlug } from '../utils/text';
+import { slugify } from '../utils/slugify';
+import { urlify } from '../utils/urlify';
 
 type SlugMethods = 'slugify' | 'urlify';
 
@@ -64,7 +65,7 @@ export class SlugController extends Controller<HTMLInputElement> {
   ) {
     const unicodeSlugsEnabled = this.allowUnicodeValue;
     const { value = this.element.value } = event?.detail || {};
-    const newValue = cleanForSlug(value.trim(), false, { unicodeSlugsEnabled });
+    const newValue = slugify(value.trim(), { unicodeSlugsEnabled });
 
     if (!ignoreUpdate) {
       this.element.value = newValue;
@@ -85,7 +86,7 @@ export class SlugController extends Controller<HTMLInputElement> {
   ) {
     const unicodeSlugsEnabled = this.allowUnicodeValue;
     const { value = this.element.value } = event?.detail || {};
-    const newValue = cleanForSlug(value.trim(), true, { unicodeSlugsEnabled });
+    const newValue = urlify(value.trim(), { unicodeSlugsEnabled });
 
     if (!ignoreUpdate) {
       this.element.value = newValue;

+ 36 - 0
client/src/utils/slugify.test.js

@@ -0,0 +1,36 @@
+import { slugify } from './slugify';
+
+describe('slugify', () => {
+  describe('slugify with unicode slugs disabled (default)', () => {
+    it('should return a correct slug', () => {
+      expect(slugify('The Price is $72.00!')).toBe('the-price-is-7200');
+      expect(slugify('This & That')).toBe('this--that');
+      expect(slugify('Lisboa é ótima à beira-mar')).toBe(
+        'lisboa--tima--beira-mar',
+      );
+    });
+  });
+
+  describe('slugify with unicode slugs enabled', () => {
+    const options = { unicodeSlugsEnabled: true };
+
+    it('should return a correct slug', () => {
+      expect(slugify('The Price is $72.00!', options)).toBe(
+        'the-price-is-7200',
+      );
+      expect(slugify('Before', options)).toBe('before');
+      expect(slugify('The', options)).toBe('the');
+      expect(slugify('Before the sun rises', options)).toBe(
+        'before-the-sun-rises',
+      );
+      expect(slugify('ON', options)).toBe('on');
+      expect(slugify('ON this day in november', options)).toBe(
+        'on-this-day-in-november',
+      );
+      expect(slugify('This & That', options)).toBe('this--that');
+      expect(slugify('Lisboa é ótima à beira-mar', options)).toBe(
+        'lisboa-é-ótima-à-beira-mar',
+      );
+    });
+  });
+});

+ 17 - 0
client/src/utils/slugify.ts

@@ -0,0 +1,17 @@
+/**
+ * Returns the supplied string as a slug, accepts options.unicodeSlugsEnabled to support
+ * additional characters being allowed.
+ */
+export const slugify = (
+  value: string,
+  { unicodeSlugsEnabled = false }: { unicodeSlugsEnabled?: boolean } = {},
+) =>
+  unicodeSlugsEnabled
+    ? value
+        .replace(/\s+/g, '-')
+        .replace(/[&/\\#,+()$~%.'":`@^!*?<>{}]/g, '')
+        .toLowerCase()
+    : value
+        .replace(/\s+/g, '-')
+        .replace(/[^A-Za-z0-9\-_]/g, '')
+        .toLowerCase();

+ 1 - 70
client/src/utils/text.test.js

@@ -1,4 +1,4 @@
-import { cleanForSlug, escapeHtml } from './text';
+import { escapeHtml } from './text';
 
 describe('escapeHtml', () => {
   it('should escape the supplied HTML', () => {
@@ -8,72 +8,3 @@ describe('escapeHtml', () => {
     );
   });
 });
-
-describe('cleanForSlug', () => {
-  require('../../../wagtail/admin/static_src/wagtailadmin/js/vendor/urlify')
-    .default;
-
-  describe('cleanForSlug without unicode slugs disabled', () => {
-    beforeEach(() => {
-      window.unicodeSlugsEnabled = false;
-    });
-
-    it('should return a correct slug which is escaped by urlify', () => {
-      /* true triggers to use django's urlify */
-      expect(cleanForSlug('Before', true)).toBe('before');
-      expect(cleanForSlug('The', true)).toBe('the');
-      expect(cleanForSlug('Before the sun rises', true)).toBe(
-        'before-the-sun-rises',
-      );
-      expect(cleanForSlug('ON', true)).toBe('on');
-      expect(cleanForSlug('ON this day in november', true)).toBe(
-        'on-this-day-in-november',
-      );
-      expect(cleanForSlug('This & That', true)).toBe('this-that');
-      expect(cleanForSlug('The Price is $72.00!', false)).toBe(
-        'the-price-is-7200',
-      );
-    });
-
-    it('should return a correct slug when not escaped by urlify', () => {
-      /* false triggers ignores django's urlify */
-      expect(cleanForSlug('Before', false)).toBe('before');
-      expect(cleanForSlug('The', false)).toBe('the');
-      expect(cleanForSlug('Before the sun rises', false)).toBe(
-        'before-the-sun-rises',
-      );
-      expect(cleanForSlug('ON', false)).toBe('on');
-      expect(cleanForSlug('ON this day in november', false)).toBe(
-        'on-this-day-in-november',
-      );
-      expect(cleanForSlug('This & That', false)).toBe('this--that');
-      expect(cleanForSlug('Lisboa é ótima à beira-mar', false)).toBe(
-        'lisboa--tima--beira-mar',
-      );
-    });
-  });
-
-  describe('cleanForSlug without unicode slugs enabled', () => {
-    beforeEach(() => {
-      window.unicodeSlugsEnabled = true;
-    });
-
-    it('should return a correct slug which is escaped by urlify', () => {
-      /* true triggers to use django's urlify */
-
-      expect(cleanForSlug('This & That', true)).toBe('this-that');
-      expect(cleanForSlug('Lisboa é ótima à beira-mar', false)).toBe(
-        'lisboa-é-ótima-à-beira-mar',
-      );
-    });
-
-    it('should return a correct slug when not escaped by urlify', () => {
-      /* false triggers ignores django's urlify */
-
-      expect(cleanForSlug('This & That', false)).toBe('this--that');
-      expect(cleanForSlug('Lisboa é ótima à beira-mar', false)).toBe(
-        'lisboa-é-ótima-à-beira-mar',
-      );
-    });
-  });
-});

+ 0 - 52
client/src/utils/text.ts

@@ -1,55 +1,3 @@
-/**
- * Utils related to text/strings.
- */
-
-declare global {
-  interface Window {
-    unicodeSlugsEnabled: boolean;
-    URLify: any;
-  }
-}
-
-/**
- * Returns the supplied string as a slug optionally using the vendor URLify util.
- * If not using URLify it will read the global unicodeSlugsEnabled and return a slugified string.
- *
- * @param {string} val - value to be parsed into a slug
- * @param {boolean} useURLify - if true, the vendor URLify will be used
- * @returns {string}
- */
-export function cleanForSlug(
-  val: string,
-  useURLify: boolean,
-  {
-    unicodeSlugsEnabled = window.unicodeSlugsEnabled,
-  }: { unicodeSlugsEnabled?: boolean } = {},
-) {
-  if (useURLify) {
-    // URLify performs extra processing on the string (e.g. removing stopwords) and is more suitable
-    // for creating a slug from the title, rather than sanitising a slug entered manually
-    const cleaned = window.URLify(val, 255);
-
-    // if the result is blank (e.g. because the title consisted entirely of stopwords),
-    // fall through to the non-URLify method
-    if (cleaned) {
-      return cleaned;
-    }
-  }
-
-  // just do the "replace"
-  if (unicodeSlugsEnabled) {
-    return val
-      .replace(/\s+/g, '-')
-      .replace(/[&/\\#,+()$~%.'":`@^!*?<>{}]/g, '')
-      .toLowerCase();
-  }
-
-  return val
-    .replace(/\s+/g, '-')
-    .replace(/[^A-Za-z0-9\-_]/g, '')
-    .toLowerCase();
-}
-
 /**
  * Escapes provided HTML.
  *

+ 40 - 0
client/src/utils/urlify.test.js

@@ -0,0 +1,40 @@
+import { urlify } from './urlify';
+
+describe('urlify', () => {
+  beforeAll(() => {
+    // load window.URLify
+    require('../../../wagtail/admin/static_src/wagtailadmin/js/vendor/urlify')
+      .default;
+  });
+
+  describe('urlify with unicode slugs disabled (default)', () => {
+    it('should return a correct slug which is escaped by urlify', () => {
+      expect(urlify('This & That')).toBe('this-that');
+
+      expect(urlify('Lisboa é ótima à beira-mar')).toBe(
+        'lisboa-e-otima-a-beira-mar',
+      );
+    });
+  });
+
+  describe('urlify with unicode slugs enabled', () => {
+    const options = { unicodeSlugsEnabled: true };
+
+    it('should return a correct slug which is escaped by urlify', () => {
+      expect(urlify('Before', options)).toBe('before');
+      expect(urlify('The', options)).toBe('the');
+      expect(urlify('Before the sun rises', options)).toBe(
+        'before-the-sun-rises',
+      );
+      expect(urlify('ON', options)).toBe('on');
+      expect(urlify('ON this day in november', options)).toBe(
+        'on-this-day-in-november',
+      );
+      expect(urlify('This & That', options)).toBe('this-that');
+
+      expect(urlify('Lisboa é ótima à beira-mar', options)).toBe(
+        'lisboa-e-otima-a-beira-mar',
+      );
+    });
+  });
+});

+ 21 - 0
client/src/utils/urlify.ts

@@ -0,0 +1,21 @@
+import { slugify } from './slugify';
+
+declare global {
+  interface Window {
+    URLify: any;
+  }
+}
+
+/**
+ * Returns the supplied string as a slug suitable for a URL using the vendor URLify util.
+ * If the vendor util returns an empty string it will fall back to the slugify method.
+ */
+export const urlify = (value: string, options = {}) => {
+  // URLify performs extra processing on the string (e.g. removing stopwords) and is more suitable
+  // for creating a slug from the title, rather than sanitising a slug entered manually
+  const cleaned = window.URLify(value, 255);
+
+  // if the result is blank (e.g. because the title consisted entirely of stopwords),
+  // fall through to the non-URLify method
+  return cleaned || slugify(value, options);
+};