RegExp to find React Components with specific properties on them - javascript

I'm trying to find a perfect RegExp to find React components with specific properties on them. The RegExp has to be used in the search field of my IDE VSCode.
Component example: <Button>
Property example: size
Component on a single line
In case the opening tag of the component is on one single line, the RegExp I found that works perfectly is this (flags are not allowed in VSCode):
/<Button.+size/
For example this will be matched until the end of size:
<Button onClick={()=>{}} size='medium'>
Component on multi-line
Sometimes the component has so many props that the company code style would want it to split it on several lines, 1 property per line, like this:
<Button
type="button"
size="tiny"
className={styles.pauseButton}
onClick={togglePaused}
title="Pause or enable automatic loading of webhook requests in the debug console."
>
I can't manage to write a RegExp to match these particular cases:
Is there a single RegExp working for both cases (and not matching anything else)?
In case one single RegExp doesn't exists for both cases, is there a RegExp to match only multi-line components with a specific prop in between its opening/closing bracket?
What I've tried
I've tried with /<Button[\s\S]*?size[\s\S]*?>/ but it overmatches cases where there is a without a size property, so it will keep matching until it find a size word somewhere.
At the moment I'm using /<Button[\n]/ which matches ALL and ONLY the split components, and then I have to manual check if they have the specific property on them. I'd still prefer a RegExp that match the split with the specific property only.
I also found this nice answer too, but it breaks if the components has other properties that have a > inside, like arrow functions and components as props. This could be a good base to start from tho. The RegExp answered is:
<Component(\s|\n)[^>]*?property
Probably it's something with lookaheads, but I'm not experienced enough...
Thanks

Related

Creating a React component and states from regex string matches

I'm moving the frontend of a project I'd written primarily with php and jquery over to react as a learning exercise. So far it just seems to be making everything a bit more convoluted but I'm hoping I'll see the benefits soon. Right now it's just good to be familiarising myself with something far more current than what I was using. But I digress...
There's one particular situation I'm translating at the moment that feels simple to do in jquery but feels like I'm having to choose between a bunch of cumbersome or not-recommended solutions with react, such as dangerouslysetinnerhtml
A user can input their own list, as raw text, which the app parses using regex to highlight quantities and items, illustrated above as highlighted by rose and green. New lines are parsed as list elements, highlighted in peach. The parsed quantities can be scaled using a range input, shown above the list. The example UI shows an example after parsing a raw string of text.
Previously - jquery
When I was using jquery I replaced regex matches with <span> elements containing data attributes to create new elements I could target. The quantity scaling function in the app could now reference the original quantity of a list item at any time using a data attribute.
e.g. I need 10 cars is parsed to become <li>I need <span class='highlight quantity' data-count='10'>10</span> <span class='highlight item' data-item='cars'>cars</span></li>
With jquery, whenever the input range is dragged, I just target all elements on the page that have the quantity class, reference their data-count and replace the span value with the current range value multiplied by that data-count. This worked well.
Now - React
I'm getting my head around react components. Referencing the illustration, above, I have a component for dialogs (as there will be other dialogs too), a component for the range input of dialogs, a component for the list, and a component for list items.
As before, when I drag the input range, I want the quantities on the page to change to reflect the new scale set by a user. When picking up react I became familiar with component states and props and thought these would solve my problem beautifully. If I had a scale state I could pass it through the components and anything in the hierarchy could reference it. As I understood it, the hierarchy was important and it was important to hold the state at the top so that lower-level components could be 'fed' it, if that's a good way of putting it. This appeared to be best practice.
But I'm having a tough time getting it to jump through hoops. Maybe I've misunderstood?
Two uncertainties
1
If I've understood the hierarchy of states correctly, I'm setting the state initially inside the App() function, like so:
function App() {
const [scaleValue, setScaleValue] = useState();
const handleScaleChange = (childData) => {
setScaleValue(childData);
}
return (
<React.Fragment>
/~~~/
<UserList rawstring={userText} scale={scaleValue} />
/~~~/
<Dialogs scale={scaleValue} setscale={setScaleValue} parentCallback={handleScaleChange}/>
</React.Fragment>
);
}
But I must use a callback function to change the state as the dialog range I'm using is nested a few levels down in components - passing it back to the state in the parent App() function and then back down to all the nested components using props. It felt much easier to just target elements with a matching class name in jquery and I'm not yet seeing the advantage of having components using states. I thought being able to target list item components with quantity states would have advantages in React that were more apparent.
2
Perhaps the main thing that has me stumped on how to proceed. In jquery, when I was parsing a raw string provided by the user, into html that I could target with specific classes, I just used some regex functions to return html that could be inserted into the dom. Example of the html is per the earlier example:
I need 10 cars is parsed to become <li>I need <span class='highlight quantity' data-count='10'>10</span> <span class='highlight item' data-item='cars'>cars</span></li>
With react, I parse the same string to the same html fine, but I've no idea how to handle it from there, logically? If I return it and insert it, it is treated as raw text and renders the html tags on page. I can use dangerouslysetinnerhtml and it shows fine, but I've loud and clear got the message that this is heavily discouraged. I want to use best practices.
In fact, I likely don't want to be returning quantities wrapped in targetable classes. I gather that I want to be able to assign states to a list item component. I have absolutely no idea what's the best approach (logically) to do this with react. I could return an array from the regex parsing but this feels needlessly complex compared to replacing a matched sub string with a wrapped version of itself.
I feel at this point I may be approaching the translation wrong (or my understanding of using the component system and states) as this feels so much more convoluted than the jquery approach I was using.
not-recommended solutions with react, such as dangerouslysetinnerhtml
That's not what dangerouslySetInnerHTML is about. It's about the fact that an unsanitized string containing HTML/JS could pose a security threat (XSS mostly). In other words, in React you have to explicitly use dangerouslySetInnerHTML if you need to be unsafe, but it's your responsibility to protect yourself, hence the name. Doesn't mean it's not recommended, just tells you to be extra careful.
the hierarchy was important and it was important to hold the state at
the top so that lower-level components could be 'fed' it, if that's a
good way of putting it.
Indeed, at first it might look overly complicated for no good reason. Today.
A few months from now if you'll have to go through that code again, or worse, if someone else will have to, this structure enforcing rules and structure makes it far more easier to make changes. You can simply right click on the "callback" function and "go to definition" in your IDE of choice and see where it's defined, instead of hoping it's not hidden in some JS file or relying on search when the function is named "handleClick" in a project with one thousand click handlers.
It felt much easier to just target elements with a matching class name in jquery
Of course it was, anyone with minimal experience in a large scale project knows this. There always are trade-offs. You need to judge if it makes sense to loose simplicity for the sake of maintainability based on the scale of the project.
With react, I parse the same string to the same html fine, but I've no idea how to handle it from there, logically?
You are mixing parsing with generating HTML. You were parsing the string and generating HTML. With React you have to parse the string and generate JSX. If your code was separating these two concerns then it would have been a lot clearer what the difference is.
Again, if you are the only one working on this and know you'll never touch it again, why bother separating these two parts? On the other hand if you do expect to touch that piece of code later or know there will be other people working on it then the smart option would be to split it so that you can properly unit test it.
I can use dangerouslysetinnerhtml and it shows fine, but I've loud and clear got the message that this is heavily discouraged. I want to use best practices.
No, that's not the point. If you use dangerouslySetInnerHTML then how are you going to interact with those highlighted numbers? document.querySelectorAll? That is indeed against the purpose of React. I think my answers above make it clear what a more suitable approach would be.
feels needlessly complex compared to replacing a matched sub string with a wrapped version of itself.
And it is because you don't understand why someone would use React. You think React is a replacement for jQuery and it is not. It is a way of writing JavaScript applications so that you don't end up with a pile of code no one can follow. Which is a problem that only exists if you eventually end up with a lot of code. Your application has what, 100 lines of JavaScript? Why are you even using jQuery?
My advice is:
Understand that people that make deliberate choices don't choose React because it's fashionable but because it solves some problems.
Figure out what those problems are. I've listed a big one, which is maintainability and that structure and separation of concerns are part of the solution.
Decide if you care about any of the problems React helps solve in any of the projects you work (or will work) on.
If you do care about these problems then put yourself in the appropriate state of mind. React is not meant to replace jQuery, find a project that would benefit from using React.
Understand that React is not the one and only tool you'll ever need.
Some more advice:
definitely have a look at useReducer and then (if you need the extra juicy bits) Redux for state management. All beginner tutorials try to stay away from them but IMO React is an empty shell without proper state management.
React is a clean way of turning state into HTML/CSS. The philosophy is that any action (e.g. a click on a "add a new row" button) should produce a state mutation that translates into manipulating some data, NOT the DOM. Your JSX is one representation of that data! And React does a great (fast) job at manipulating the DOM to reflect the new JSX representation. So start thinking your application in terms of input-output, data structures and actions/reducers that manipulate these data structures.
force yourself to unit test (or, better, TDD) your actions and reducers. Completely decoupled from JSX and DOM! Your entire application logic should be testable in Node CLI. This to me (that you can completely separate logic from presentation) is a major win (and is the base of React Native too).
have a look at https://storybook.js.org/ - this one is another one of those fantastic tools (not only for React) that will completely change your development experience.
be wary of using "component libraries". Most "complicated" things turn into child's play when you really understand how to design them correctly.
be prepared to spend 3x the time you spent before on implementing really simple stuff for a while, until you familiarize yourself with the core concepts and philosophy.

Create custom Range in Word Javascript API / Office.js

I understand that many methods of the Word Javascript API return a Range or RangeCollection. But, is there a constructor function developers can use to create a new Range directly?
My use case is that I need to look at each paragraph, identify errors, and syntax highlight them. So, I'd like to just get the plain text of the paragraph using the API, find the errors on my own, and then use that information to create a Range that I can use to decorate the text (or add a Bounday/ContentControl to refer to it later).
there are a couple of options for you.
a. Use search - you can scope it to the paragraph. You can also use range.compareLocationWith to compare if the found range is the same and remove dupes. So the idea is you grab a paragraph, analyze, find an issue, do a search to get the range (and make sure is the range you need). Once you have a range you can apply formatting, insert content controls or insert, replace content.
b. Use split - is a method you can use to decompose a paragraph into words (each a range).
c. ExpandTo - to extend a given range to another.
d. on any object you can use .getRange() to get its associated range.

Multiline text with React

I am working with react and I need to do a multiline text.
<p>{"You'll receive offers for up to one week, which you can review."}</p>
It should return
You'll receive offers for up to one week,
which you can review
I am using that pattern {"..."} due to JSLint rules and I like that.
So, what should I do to accomplish what I want?
Using {..} for jslint is not a good reason, things inside {} are evaluated differently. For plain html just do:
<p>You'll receive offers for up to one week,<br />which you can review.</p>
Although forcing a line break like this is considered poor practice for any html without a really good reason (because on different screen widths, font sizes, resolutions, translations, the break is likely incorrect). It's better to limit the width of the container so it breaks where you want it to and at least it will break naturally if things change.
In HTML, line breaks are denoted by <br />. So you would want:
<p>
{"You'll receive offers for up to one week,"}
<br />
{"which you can review."}
</p>
You can use html br tag for the new line
<p>{"You'll receive offers for up to one week, <br/>which you can review."}</p>
Hope that this helpful.

Regex to search inside contents of file

I am using software to search inside txt files with Regex, For example
So I want to find files which Contain "Black" under "color" under "clothes", So the regex should highlight "Black" which located in line 7 only.
My aim here is to follow the order no mater how many lines between terms.
I will be more than thankful if you explain "regex" so I know what I have missed.
Thanks in advance
You can use the following regex for matching the given 'Black':
/.+?Clothes.+?Colour.+?(Black)/s
Description
Demo
http://regex101.com/r/gD9iD3
Discussion
The regex here may not fit all your needs. It uses .+? for navigating between the searched elements. This is really imprecise: the "Red" case that you have outputted in your comments is a guenine POC.
The next step here is to determine how elements (Clothes, Colour etc) are structured. Armed with this knowledge, the regex can be strengthened. .+? will be replaced then by more specific elements.
If the regex is used in a Javascript context, the s modifier is not available.
To work around this limitation, the following structure: .+? can be replaced with [\s\S]+?.

Backreference each character

For the sake of simplicity & learning something new, please don't suggest using two separate replace functions. I know that's an option but I would rather also know how to do this (or if it's not possible).
'<test></test>'.replace(/<|>/g,'$&'.charCodeAt(0))
This is what I've got so far. This sample code is, as you can tell, for another piece of code to escape HTML entities while still using innerHTML (because I do intend to include a few HTML entities such as small images, so again please don't suggest textContent).
Since I'm trying to replace both < and >, the problem is converting each individual one to their respective character codes. Since regular expressions allow for this "OR" condition as well as backreferences to each one, I'm hoping there's a way to get the reference of each individual character as they're replaced. $& will return <><> (because they're replaced in that order), but I don't know how to get them as they're replaced and take their character codes for the HTML entities. The problem is, I don't know what to use in this case if anything.
If that explanation wasn't clear enough, I want it to be something like this (and this is obviously not going to work, it'll best convey what I mean):
Assuming x is the index of the character being replaced,
'<test></test>'.replace(/<|>/g,'$&'.charCodeAt(x))
Hopefully that makes more sense. So, is this actually possible in some way?
'<test></test>'.replace(/[<>]/g,function(a) {return '&#'+a.charCodeAt(0)+';';});
I've put the characters in a square-bracket-thing (don't know it's proper name). That way you can add whatever characters you want.
The above will return:
<test></test>

Categories

Resources