DEV Community

Cover image for Create slug using title in React
Deepak Jaiswal
Deepak Jaiswal

Posted on

Create slug using title in React

I have seen some time we are using _id in routing. and we get the data based on _id but it shows our original data id that i have leak. and based on SEO the id is not best way to add in url.

Like i'm creating a blog detail page based on id it looks bad but when i am using slug based on title. it looks good.

And the user understand by the url.

function getSafeRegexpString(input) {
  return input
    .split("")
    .map((char) => `\\${char}`)
    .join("");
}
Enter fullscreen mode Exit fullscreen mode

I am using the package diacritics which is remove unnecessary text.

import { remove as stripAccents} from 'diacritics';
function format(
  input,
  delimiter,
  ignoreInvalid = false
) {
  const harmonized = stripAccents(input).trim().toLowerCase();
  const safeDelimiter = getSafeRegexpString(delimiter);

  if (ignoreInvalid) {
    return harmonized.replace(/\s+/g, delimiter);
  }

  return harmonized
    .replace(new RegExp(`[^a-z0-9\\u0900-\\u097F${safeDelimiter}]+`, "g"), delimiter) // Replace all non-valid caracters by delimiter
    .replace(new RegExp(`${safeDelimiter}+`, "g"), delimiter) // Remove multiple delimiters repetition
    .replace(new RegExp(`^${safeDelimiter}`, "g"), "") // remove delimiter at the beginning
    .replace(new RegExp(`${safeDelimiter}$`, "g"), ""); // remove delimiter at the end
};
Enter fullscreen mode Exit fullscreen mode

You can also put your regex for custom change. I have put [^a-z0-9\u0900-\u097F${safeDelimiter}] for hindi words.

export default function slugify(
  node,
  options = { delimiter: "-", prefix: "" }
) {
  if (!options.delimiter) options.delimiter = "-";
  if (!options.prefix) options.prefix = "";

  if (!node || typeof node === "boolean") {
    return "";
  }

  const { delimiter, prefix } = options;

  // boolean
  if (typeof node === "boolean") {
    return ""; // not much we can do here
  }

  // string, number
  if (typeof node === "string" || typeof node === "number") {
    const harmonizedPrefix = format(prefix, delimiter, true);
    const harmonizedNode = format(String(node), delimiter);

    if (harmonizedPrefix) {
      return `${harmonizedPrefix}${delimiter}${harmonizedNode}`;
    }

    return harmonizedNode;
  }

  // ReactPortal
  if ("children" in node) {
    return slugify(node.children);
  }

  // ReactElement
  if ("type" in node) return slugify(node.props.children, options);

  // ReactFragment (including array of nodes)
  if (Symbol.iterator in node) {
    return slugify(
      Array.from(node)
        .map((subNode) => slugify(subNode, { delimiter }))
        .join(delimiter),
      options
    );
  }

  // unhandled case
  return "";
};
Enter fullscreen mode Exit fullscreen mode

Top comments (0)