Differentiate among comparable values through placement regex

I'm currently tackling a challenge involving regex as I work on breaking down shorthand CSS code for the font property. Here is my progress thus far:

var style = decl.val.match(/\s*(?:\s*(normal|italic|oblique)){1}/i); style = style ? style[1] : "";
var variant = decl.val.match(/\s*(?:\s*(normal|small-caps))/i); variant = variant ? variant[1] : "";
var weight = decl.val.match(/\s*((?:\s*(?:normal|bold|bolder|lighter|\d+(?:\%|in|cm|mm|em|rem|ex|pt|pc|px))){1})/i); weight = weight ? weight[1] : "";
var size = decl.val.match(/\/\s*((?:\s*(?:xx-small|x-small|small|medium|large|x-large|xx-large|larger|smaller|\d+(?:\%|in|cm|mm|em|rem|ex|pt|pc|px))){1,2})/i); size = size ? size[1] : "";
var height = decl.val.match(/\s*(?:\s*(normal|inherit|\d+(?:\%|in|cm|mm|em|rem|ex|pt|pc|px))){1}/i); height = height ? height[1] : "";
var family = decl.val.match(/\s*(?:\s*([a-zA-Z\-\,\'\"\s]+))(?:,|;)/i); family = family ? family[1] : "";
var values = decl.val.match(/\s*(?:\s*(caption|icon|menu|message-box|small-caption|status-bar)){1}/i); values = values ? values[1] : "";

While everything is running smoothly, there's an issue when using this specific string:

font: normal small-caps 120%/120% fantasy, sans-serif;

This results in style, variant, weight, and height all being set to "normal":

style --> "normal"
variant --> "normal"
weight --> "normal"
height --> "normal"

The problem lies with the regex matching the first instance without verifying if another value should be taken instead. The desired outcome should look like this:

style --> "normal"
variant --> "small-caps"
weight --> "120%"
height --> 

If you have any questions or need further clarification, please don't hesitate to ask. Thank you for your assistance!

Answer №1

There seems to be a minor issue with the forward slash placement between weight and sizes. To resolve this, consider combining into one regex pattern where everything except anchors is optional. This will help align things properly to avoid 'normal' appearing on most variables.

Edit I came across a reference that details how CSS Font Shorthand Property parsing works: http://www.w3schools.com/cssref/pr_font_font.asp

edit2 The hard spaces delimiters have been adjusted to come after the optional parts and between the required parts.

 #  /(?:(?:(normal|italic|oblique|initial|inherit)\s+)?(?:(normal|small-caps|initial|inherit)\s+)?(?:((?:normal|bold|bolder|lighter|initial|inherit|\d+))\s+)?(?:(smaller|small|x-small|xx-small|medium|larger|large|x-large|xx-large|initial|inherit|\d+(?:\%|in|cm|mm|em|rem|ex|pt|pc|px))(?:\/(normal|initial|inherit|\d+(?:\%|in|cm|mm|em|rem|ex|pt|pc|px)))?\s+)(?:(initial|inherit|(?:"[^"]*"|'[^']*'|[a-zA-Z-]+)(?:\s*,\s*(?:"[^"]*"|'[^']*'|[a-zA-Z-]+))*))|(caption|icon|menu|message-box|small-caption|status-bar|initial|inherit))/

 ####  CSS - Font Shorthand Property  
 ####  Reference:  http://www.w3schools.com/cssref/pr_font_font.asp    
 #### --------------------------------
 #### font:     

 (?:
      #### User Defined Fonts
      #### ------------------

      ##### Style (optional)
      (?:
           (                        # (1 start), Style
                normal
             |  italic
             |  oblique
             |  initial
             |  inherit 
           )                        # (1 end)
           \s+   # delimiter
      )?

      ##### Variant (optional)
      (?:
           (                        # (2 start), Variant
                normal
             |  small-caps
             |  initial
             |  inherit 
           )                        # (2 end)
           \s+   # delimiter
      )?

      ##### Weight (optional)
      (?:
           (                        # (3 start), Weight
                (?:
                     normal
                  |  bold
                  |  bolder
                  |  lighter
                  |  initial
                  |  inherit 
                  |  \d+ 
                )
           )                        # (3 end)
           \s+   # delimiter
      )?

      ##### Size (required)
      (?:
           (                        # (4 start), Size
                smaller
             |  small
             |  x-small
             |  xx-small
             |  medium
             |  larger
             |  large
             |  x-large
             |  xx-large
             |  initial
             |  inherit
             |  \d+ 
                (?: \% | in | cm | mm | em | rem | ex | pt | pc | px )
           )                        # (4 end)

           #####  Line Height (optional)
           (?:
                /                   # Separator
                (                   # (5 start), Line height
                     normal
                  |  initial
                  |  inherit
                  |  \d+ 
                     (?: \% | in | cm | mm | em | rem | ex | pt | pc | px )
                )                   # (5 end)

           )?

           \s+   # delimiter 
      )

      ##### Family (required)
      (?:
           (                        # (6 start), Family
                initial
             |  inherit
             |  (?: " [^"]* " | ' [^']* ' | [a-zA-Z-]+ )
                (?:
                     \s* , \s* 
                     (?: " [^"]* " | ' [^']* ' | [a-zA-Z-]+ )
                )*
           )                        # (6 end)
      )

   |  

      #### OR, 
      #### Use the Fonts used by these OS elements
      #### ------------------

      #### Values (required, if used)
      (                             # (7 start), Use values
           caption
        |  icon
        |  menu
        |  message-box
        |  small-caption
        |  status-bar
        |  initial
        |  inherit
      )                             # (7 end)
 )

Perl Test case

$str = 'font:normal small-caps 120%/120% "Times New Roman", sans-serif;';

if ( $str =~ /(?:(?:(normal|italic|oblique|initial|inherit)\s+)?(?:(normal|small-caps|initial|inherit)\s+)?(?:((?:normal|bold|bolder|lighter|initial|inherit|\d+))\s+)?(?:(smaller|small|x-small|xx-small|medium|larger|large|x-large|xx-large|initial|inherit|\d+(?:\%|in|cm|mm|em|rem|ex|pt|pc|px))(?:\/(normal|initial|inherit|\d+(?:\%|in|cm|mm|em|rem|ex|pt|pc|px)))?\s+)(?:(initial|inherit|(?:"[^"]*"|'[^']*'|[a-zA-Z-]+)(?:\s*,\s*(?:"[^"]*"|'[^']*'|[a-zA-Z-]+))*))|(caption|icon|menu|message-box|small-caption|status-bar|initial|inherit))/)
{
    print "\nmatched  '$&'\n\n";
    print "style   = '$1'\n";
    print "variant = '$2'\n";
    print "weight  = '$3'\n";
    print "size    = '$4'\n";
    print "height  = '$5'\n";
    print "family  = '$6'\n";
    print "values  = '$7'\n";
}

Output >>

matched  'normal small-caps 120%/120% "Times New Roman", sans-serif'

style   = 'normal'
variant = 'small-caps'
weight  = ''
size    = '120%'
height  = '120%'
family  = '"Times New Roman", sans-serif'
values  = ''

Answer №2

Here is a method you can use to manipulate attributes in a string:

Start by identifying one attribute and then removing it from the original string. Proceed to search for the next attribute in the updated string.

Below is an illustration focusing on the primary attribute within the string:

var str = decl.val;

function removeFromString(str, result) {
    console.log(result);
    return str.slice(0, result.index) + str.slice(result.index + result[0].length);
}

var style = str.match(/\s*(?:\s*(normal|italic|oblique)){1}/i); 
if(style) {
    str = removeFromString(str, style);
}
style = style ? style[1] : "";

To visualize this process, I have created a JSFiddle.

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

Attempting to generate a fresh document by duplicating the data from a specific variable

Currently attempting to generate a new csv file within a specific directory. The goal is to save the data of a variable inside the created csv file: handleRequest(req, res) { var svcReq = req.body.svcReq; var csvRecData = JSON.stringify(req.bod ...

Tips for properly showcasing images on a webpage after ensuring all other content has loaded

Is there a way to have an image load last on a webpage after all other content has been loaded? I have an image that is retrieved from a database when a button is pressed, but I would prefer for the entire page to load first and then display the image. C ...

Is it possible to apply CSS styling to all placeholders in a Sencha Touch application?

Having trouble figuring out how to style all the placeholders in my application with CSS. I've attempted a few different methods: .customField input::-webkit-input-placeholder { color: #2e4bc5; } .x-text-field input::webkit-input-placeholder{ c ...

Tips for establishing breakpoints within Material UI grid for achieving responsiveness

I am currently utilizing Material ui's Grid component to organize my user interface elements. Here is the code snippet: <Grid container spacing={3}> <Grid container item xs={12} sm={12} md={12} style={{ marginTop: '-1.5%', marginRi ...

Caution: Exercise caution when rendering components in React due to unstable_flushDiscreteUpdates

Trying to utilize map to render a component, but encountering a warning: Warning: unstable_flushDiscreteUpdates: Cannot flush updates when React is already rendering. MyBooks.js import React, { useState, useEffect } from 'react'; import Action ...

Adding an HTML arrow icon within a button

As I work on creating an HTML email, my aim is to incorporate a right arrow onto an HTML button. To achieve this, I have opted to utilize a special character and apply the transform-rotate property. However, I am facing an issue where the text and arrow a ...

Trouble detecting click event in jQuery after triggering radio button in HTML

Encountering a peculiar jQuery issue where triggering a click on a radio button does not fire completely and is ignored by an on click function, while a similar call to the jQuery trigger method is successfully captured. In the below jQuery snippet, a < ...

What could be causing the issue of CSS Styles not being applied to an Angular 2 component with Vaadin elements?

Currently, I am immersed in the tutorial on Vaadin elements using Angular 2 that I stumbled upon here In section 5.3, Styles are applied to the app.component.ts as shown below import { Component } from [email protected]/core'; @Component({ select ...

Navigating through a predetermined list of HTML pages with next and previous options

Hey there, I'm in a bit of a quandary at the moment. I've been searching on Google for quite some time now, but unfortunately, I can't seem to find what I'm looking for. Hopefully, you guys can lend me a hand. What I'm trying to d ...

Enhancing User Experience with Bootstrap V5 Form Validation and Sweetalert2: Displaying a Message of Success Upon Successful Submission

I am currently working on implementing a simple form using Bootstrap 5 that includes validation. My goal is to display an alert message when the form field is successfully submitted using Sweetalert2. Below is the code I have: HTML <form action=&q ...

Sort the DOM elements in jQuery based on their CSS color property

Displayed on the page below is a list of usernames in a random order. I'm looking to sort them using jQuery in the following sequence: red blue green purple black This is my current progress: <script type="text/javascript"> $(function() { ...

Conceal the scroll bar while still allowing for scrolling functionality

In this code snippet, I am trying to maintain the scroll position of two blocks by syncing them together. Specifically, I want to hide the scrollbar of the left block while scrolling the right one. If anyone has any suggestions or solutions for achieving ...

"Scraping with a CSS selector in Scrapy produces an incomplete JSON string

Greetings, I am new to Python and specifically web scraping. My current project involves scraping Walmart, but I have encountered a problem. I am using this regular expression to extract a JSON string from the response: __WML_REDUX_INITIAL_STATE__ =*(.*&b ...

"Uncaught Error: Unable to retrieve null properties" encountered while utilizing regex match in cheerio web scraping

Extracting text from brackets in HTML using regex: <dl class="ooa-1o0axny ev7e6t84"> <dd class="ooa-16w655c ev7e6t83"> <p class="ooa-gmxnzj">Cekcyn (Kujawsko-pomorskie)</p> </dd> <dd class="ooa-16w655c ev7e6t ...

Prevent unnecessary re-renders of components by optimizing state changes with hooks

In my Layout component, there is a Table component with an Entry component for each row. Each row can be selected, and when a row is selected, it is added to the state so that all selected entries can be sent to a REST service later using a button. The i ...

Modify the parent's style in CSS based on the presence of certain specified children

I'm working with an HTML element that can contain a child with the ID 'slideshow' <div id='content'> <div id='slideshow'> </div> </div> Alternatively, it could have a different child like t ...

Can you explain how JSON and AJAX are different when used in conjunction with jQuery?

Is it true that JSON serializes all data, preventing problems with client-side issues like cross-browser support? I've found using AJAX with jQuery to be straightforward, but I'm still unclear about the differences. I have also come across anot ...

The jQuery Deferred feature on Ajax is failing to properly pass the array in the data option as an array, instead converting

I am facing an issue in my application where I want to use jQuery deferred to handle Ajax success and error uniformly from a central location. It works perfectly fine when I pass strings in the data option, but when I try to pass an array, it gets sent as ...

Pressing the enter key in an AngularJS form does not trigger submission

Having trouble with a login form that won't submit when the user presses enter. While the form works fine when the "Login" button is clicked, hitting enter doesn't trigger submission and leads to some unexpected behavior: The ng-submit associat ...

Pattern for validating 19-digit Visa and Discover cards using Regex technology

Presently, I have implemented the regex patterns below but unfortunately they do not cater to 19-digit cards for both Visa and Discover. Could you please provide assistance with this issue? visaCardPattern: /^4[0-9]{12}(?:[0-9]{3})?$/ discoverCardPatte ...