Add 'http://' to hrefs that do not have a protocol specified in Angular

I've been trying to come up with a solution to automatically add "http://" to any href links that don't already have it before the link. Here is what I currently have:

static correctUrls(input: string): string {

  // extract all hrefs from the input
  let urls = input.match('<a[^>]* href="([^"]*)"/g');

  // if no urls found, return original input
  if (!urls) {
    return input;
  }

  // remove duplicate urls
  urls = urls.filter((item, pos) => {
    return urls.indexOf(item) === pos;
  });

  // if no urls in the input, return original input
  if (!urls) {
    return input;
  }

  for (const url of urls) {

    // check if url does not start with https://
    if (!url.match('^ (http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$')) {
      input = input.replace(url, 'https://' + url);
    }
  }
  return input;
}

Any assistance would be greatly appreciated. Please explain how your regex solution works. Most solutions I've come across so far return duplicate matches or behave strangely when used with input.match.

Input example:

<p> We love
  <a href="https://google.com"
     rel="noopener noreferrer"
     target="_blank">Google</a>
  and
  <a href="Facebook.com"
     rel="noopener noreferrer"
     target="_blank">Facebook</a>.
</p>

Expected output:

<p> We love
  <a href="https://google.com"
     rel="noopener noreferrer"
     target="_blank">Google</a>
  and
  <a href="https://Facebook.com"
     rel="noopener noreferrer"
     target="_blank">Facebook</a>.
</p>

Answer №1

If you're working with Angular, the recommended approach is to utilize the DOMParser for handling this task. By using this method, you can easily target all elements containing anchor tags and then implement a regex check to identify URLs starting with either http or https.

export class UrlCorrector {
  static correctUrls(input: string): string {

    const parser = new DOMParser();
    const document = parser.parseFromString(input, 'text/html');

    // gather all anchor tags from the input
    const anchorTags = document.getElementsByTagName('a');

    // if there are no anchor tags, return the original input
    if (anchorTags.length === 0) {
      return input;
    }

    const urls: string[] = [];

    // loop through all anchor tags to extract their URLs
    // tslint:disable-next-line: prefer-for-of
    for (let i = 0; i < anchorTags.length; i++) {

      const href = anchorTags[i].href;
      let url = href;

      // check if the URL contains the hostname, indicating it lacks the http protocol
      if (href.includes(location.hostname)) {

        // extract only the last part of the link e.g., `localhost:4200/submissions/facebook.com` will become `facebook.com`
        url = href.substr(href.lastIndexOf('/') + 1);
      }
      urls.push(url);
    }

    for (const url of urls) {

      // if the URL doesn't have a protocol specified, add https:// to the beginning
      // tslint:disable-next-line: max-line-length
      if (!url.match('^ (http: \/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$')) {
        input = input.replace(url, 'https://' + url);
      }
    }
    return input;
  }
}

Answer №2

Using Regex may not be the best solution for this task. Since you are already working with JavaScript, there are plenty of tools available for DOM manipulation that can achieve the desired outcome. It is recommended to explore these options as they are more suitable for your requirement!

If you insist on using regex, you can try href="(?!https?:\/\/)()[^"]+".

  • href=": Searches for the href=" string to initiate the match
  • (?!https?:\/\/): Ensures that the URL does not start with http:// or https://
  • (): Empty capture at the beginning of the URL that needs modification - replace this with your desired text
  • [^"]+": Matches everything until the next quotation mark, representing the rest of the URL

Check out the Demo for a visual representation.

Here's a sample JavaScript code snippet utilizing this approach:

var x = '<p> We love <a href="https://google.com" rel="noopener noreferrer" target="_blank">Google</a> and <a href="Facebook.com" rel="noopener noreferrer" target="_blank">Facebook</a>. <a href="www.example.com" rel="noopener noreferrer" target="_blank">Facebook</a>. <a href="http://www.example.com" rel="noopener noreferrer" target="_blank">Facebook</a>. </p>'
var urls = x.match('href="(?!https?:\/\/)()([^"]+)"')

console.log("https://" + urls[2])

'https://Facebook.com'

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

instructions on modifying a singular row within a v-data-table (excluding design changes, focusing on the data itself)

For this specific scenario involving v-data-table, I encountered a challenge in finding an answer. While I am aware that templates and slots can be utilized to modify columns, my query pertains to reflecting values in only one row. Essentially, I aim to ad ...

The Angular CLI release does not match the Angular version

After updating Angular to version 9, my previously smoothly running angular project started throwing this error: This peculiar error message popped up: This version of CLI is only compatible with Angular versions 0.0.0 || ^10.0.0-beta || >=10.0.0 <1 ...

Having trouble retrieving JSON data from the open weather API

I'm working on a small website to display the weather of a specific city using an API. However, I am facing an issue where I can't seem to display the temperature from the response. Below are snippets of my JavaScript and HTML files: var ap ...

Generating step definitions files automatically in cucumber javascript - How is it done?

Is there a way to automatically create step definition files from feature files? I came across a solution for .Net - the plugin called specflow for Visual Studio (check out the "Generating Step Definitions" section here). Is there something similar avail ...

Prevent incorrect data input by users - Enhancing JavaScript IP address validation

I have been trying to create a masked input field for entering IP addresses, but every solution I come across seems to have some flaws. The best solution I found so far is , but it still allows values higher than 255 to be entered. It works fine initially ...

unable to navigate to next or previous page in react-bootstrap-table2-paginator

I successfully implemented a table with pagination using react-bootstrap-table2-paginator. On each page number click, it calls an API to fetch the table data. However, I encountered issues with the next page, previous page, and last page buttons not workin ...

Using Query strings in JavaScript: A Quick Guide

I recently completed a calculator project with only two pages. However, I am struggling to figure out how to pass input field values from one page to another. Despite trying multiple methods, nothing seems to be working. Does anyone know how to successful ...

Using TypeORM's QueryBuilder to select a random record with a nested relation

Imagine a scenario where I have the following entities: User @Entity('user', { synchronize: true }) export class UserEntity { @PrimaryGeneratedColumn('uuid') id: string; @Column() firstName: string; @Column() lastName: s ...

What is the process for passing a component as a parameter to a function within a different component?

Within my scenario, I have a series of components '1,2,3,...' imported into another primary component 'A'. Within component 'A', certain operations are performed and a filtered component is then returned from the list of compo ...

Unable to post links on Facebook when using Angular 7

Is it possible to share a URL on Facebook using Angular 7 without server-side rendering like Angular Universal or prerender? I attempted to update meta tags for Facebook share during the click function, but it did not work. What is the most effective way t ...

changing a one-dimensional array into a two-dimensional array using TypeScript

I need help transforming a flat array into a 2D array, like this: ['-', '-', '-', '-', '-', '-', '-', '-', '-'] My desired output is: [ ['-', '-&apo ...

Utilizing TypeScript in Kendo UI for JQuery

I have implemented KendoUI for JQuery using TypeScript. Here is an excerpt from my "package.json" file: "dependencies": { "@progress/kendo-theme-material": "^3.19.2", "@progress/kendo-ui": "^2020.3.915 ...

Jspsych: Centering and aligning 3 p tags to the left on the page

Feeling pretty stuck at the moment. Here's what I have visually right now: https://i.sstatic.net/FUzgM.png I added a caption in Comic Sans and an arrow using MS Paint. Each line with color swatches is wrapped in a p tag. The goal is to center thes ...

Learn the method for incorporating a changing name into a radio button with Vue.js

How do I dynamically name radio buttons? <tr v-for="user in users"> <td> <input type="radio" :name="groups_[[ user.id ]]" v-bind:value="photographer" v-bind:checked="user.group.name == photographer"> <label>photographer ...

"Working with Node.js: Implementing a Static Variable in Module Ex

I am working on exporting a module that will store information in a hashtable to be accessed later. However, I am encountering difficulties in maintaining the consistency of the hashtable as a global variable throughout the application. Here is my current ...

Understanding the reactivity and data management in Vue.js through the use of mixins

I am attempting to create a toggle flag that can switch between boolean values of true and false based on specific conditions. // main.js new Vue({ el: `#app`, render: h => h(App,{ props:{ todoID: this.dataset.id } }) } ...

What is the best way to revert the Highcharts bar color back to its default color?

I am currently working with Highcharts version 4.1.10 In my bar chart, I have implemented a feature where the color of the bar changes when its value exceeds a certain threshold. //This function is called at regular intervals by a timeout function myTime ...

Tips on implementing Piwik JavaScript code within app.js on Express

I am trying to implement Piwik tracking on my Express website using JavaScript code. I placed the code in my app.js file but encountered an error. Here is the JavaScript code snippet: <script type="text/javascript"> var _paq = _paq || []; ...

Is it possible for Typescript to utilize Webpack's UMD feature for importing

Is there a method in TypeScript to import a module wrapped by webpack UMD (Universal Module Definition)? For instance: npm install knockback The file .js (node_modules/knockback/knockback.js) starts like this: (function webpackUniversalModuleDefinition( ...

Testing the HttpInterceptor functionality in Angular 4 through unit tests

I'm looking for guidance on testing the HttpInterceptor functionality provided by Angular 4. I've created an interceptor based on examples, but I'm unsure about how to properly test it. Below is my interceptor code, and I aim to verify that ...