Is it always safe to insert a linebreak after a semicolon? - javascript

I am having an issue checking in a minified JavaScript file into Clearcase. The file in question is a single line, well over the 8000 character limit that Clearcase imposes.
I know that JavaScript interpreters do some tricky things inserting semicolons at linebreaks, but I am wondering if it should always be safe to add a linebreak after a semicolon. Is it possible that doing so would change the meaning of the JavaScript code?

To answer your immediate question: yes, you can add line breaks after a semicolon that ends a statement. There may be other uses of semicolons (e.g. inside a string or regex) in the file, and you shouldn't touch those.
I have another question for you: Why are you checking in a minified JavaScript file? I would think it's better to check in the original verbose JavaScript source. Plus, version control systems aren't effective in general for files of only one line. If you are already checking in the original JavaScript, you now have to maintain consistency between the two files (i.e. when you change one you must refresh the other). I suggest checking in a script that will minify the original when you deploy it instead of keeping the minified version in Clearcase.

A semicolon might be encapsulated in a string. Adding a line break to the string would change the meaning of the javascript.

If the semicolon is inside of a string or a regex (such as var rex = /;/g; — it's only safe to insert a line break after the second semicolon), then yes, that would obviously be a problem. Otherwise, it's always safe to have a line break after a statement.

Admin or maybe developer needs to run this command on each VOB where artifact is stored
(in context of desired VOB)
(not 100% sure about the -supertype, "binary_file" might be better)
(not 100% sure about the -mergetype, "copy" might be better!)
(you can always change this later via -replace option)
cleartool mkeltype -nc -supertype text_file -manager z_whole_copy -mergetype auto text_file_minified
This can be used to correct files that failed trying to checkin.
They have probably been created with a type of "text_file"
individual lines of text_file types cannot exceed 8000 characters.
cleartool chtype -nc -force text_file_minified jquery-1.8.2.min.js
PUT this file on your desktop/dev machine where you checkin.
Remove any leading spaces.
# AAA.magic
# This needs to copied to all developer desktops
# copy it next to default.magic (or cc.magic)
# under ...\ClearCase\config\magic
# Leave these from the default.magic just in case
# files are processed in alphabetic order, hence the AAA prefix
# Check stat type
directory : -stat d ;
block_device : -stat b ;
char_device : -stat c ;
socket : -stat s ;
fifo : -stat f ;
# minified javascript and CSS
# some of these violate the 8000 character per line limit
# of clearcase text tools/type managers
# *.min.js
text_file_minified : -name "*.[mM][iI][nN].[jJ][sS]" ;
# *.min.css
text_file_minified : -name "*.[mM][iI][nN].[cS][sS][sS]" ;

A semi-colon in Javascript always determines the end of a code line.
Given this, it should always be safe to add a line break after a semi-colon unless that semi-colon is part of a string.

Related

Applescript with do Javascript and passed Applescript Variable

I have written a script that has automated the creation of products on a website I administer. In my process I upload JPEG images of the products and pull the Keywords that are tagged in the JPEG to add into the product information. In this process I use Applescript to Activate Safari and process a Javascript line of code. The line of code includes the a variable that is derived from Applescript Shell Script.
Code below
tell application "Finder"
set sourceFolder to folder POSIX file "/Users/<username>/Desktop/Upload/Temp/HighRes/"
set theFiles to files of sourceFolder
set inputPath to "/Users/<username>/Desktop/Upload/Temp/"
end tell
repeat with afile in theFiles
set filename to name of afile
set fname to text 1 thru ((offset of "." in filename) - 1) of filename
--INPUT CODE TO BE LOOPED OVER BELOW--
--Add Image Keywords from Metadata--
try
set pathVAR1 to "/Users/<username>/Desktop/Upload/Temp/HighRes/"
set pathVAR2 to pathVAR1 & filename
set myvar to do shell script "mdls -name kMDItemKeywords " & quoted form of pathVAR2
set var1 to ((offset of "(" in myvar) + 1)
set var2 to ((length of myvar) - 1)
set myKeywords to ((characters var1 thru var2 of myvar) as string)
--Inputs the Keywords from the Image Metadata--
tell application "Safari"
activate
do JavaScript "document.getElementById('ctl00_cphMainContent_txtKeyWords').value = \"" & myKeywords & "\";" in current tab of window 1
end tell
end try
--END OF CODE TO BE LOOPED OVER--
end repeat
==End Code==
Problem:
The code below is not passing the variable myKeywords to Safari, but if I run a dialog it will appear in the dialog.
do JavaScript "document.getElementById('ctl00_cphMainContent_txtKeyWords').value = \"" & myKeywords & "\";" in current tab of window 1
I don't have a specific solution that will definitely solve your problem, but I do have a number of observations about your script with recommendations on how it can be changed to improve its speed, robustness and adherence to principles of best practice.
Get rid of that try block. You have no idea what's happening in your script when things go wrong if you're masking the errors with unnecessary error-catching. The only line that needs to be enclosed in try...end try is do shell script, but only put it in once you know your code is working. In general, try blocks should only be used:
when your script has the potential to throw an error that is entirely predictable and explainable, and you understand the reasons why and under what conditions the error occurs, allowing you to implement an effective error-handling method;
around the fewest possible number of lines of code within which the error arises, leaving all lines of code whose existence doesn't depend on the result of the error-prone statement(s);
after your script has been written, tested, and debugged, where placing the try block(s) no longer serves to force a script to continue executing in the wake of an inconvenient error of unknown origin, but has a clear and well-defined function to perform in harmony with your code, and not against it.
As a general rule in AppleScript, don't use Finder to perform file system operations if you can avoid it: it's slow, and blocks while it's performing the operations, meaning you can't interact with the GUI during this time. Use System Events instead. It's a faceless application that won't stop other things operating when it's performing a task; it's fast, in the context of AppleScript and Finder in particular, and isn't prone to timing out quite so much as Finder does; it handles posix paths natively (including expansion of tildes), without any coercion necessary using POSIX file; it returns alias objects, which are the universal class of file object that every other scriptable application understands.
There are a couple of instances where Finder is still necessary. System Events cannot reveal a file; nor can it get you the currently selected files in Finder. But it's simple enough to have Finder retrieve the selection as an alias list, then switch to System Events to do the actual file handling on this list.
This is curious:
set filename to name of afile
set fname to text 1 thru ((offset of "." in filename) - 1) of filename
Am I right in thinking that fname is intending to hold just the base file name portion of the file name, and this operation is designed to strip off the extension ? It's a pretty good first attempt, and well done for using text here to itemise the components of the string rather than characters. But, it would, of course, end up chopping off a lot more than just the file extension if the file name had more than one "." in it, which isn't uncommon.
One way to safely castrate the end of the file name is to use text item delimiters:
set filename to the name of afile
set fname to the filename
set my text item delimiters to "."
if "." is in the filename then set fname to text items 1 thru -2 of the filename as text
You should then be mindful or resetting the text item delimiters afterwards or there'll be consequences later on when you try and concatenate strings together.
Another way of chopping of the extension without utilising text item delimiters is string scanning, which is where you iterate through the characters of a string performing operations or tests as you go, and achieving the desired outcome. It's speedier than it sounds and a powerful technique for very complex string searching and manipulations:
set filename to the name of afile
set fname to the filename
repeat while the last character of fname ≠ "."
set fname to text 1 thru -2 of fname
end
set fname to text 1 thru -2 of fname
You could also retrieve the name extension property of the file, get its length, and remove (1 + that) many characters from the end of the file's name. There a myriad ways to achieve the same outcome.
This is wrong in this particular instance:
set myKeywords to ((characters var1 thru var2 of myvar) as string)
characters produces a list, which you then have to concatenate back into a string, and this is unsafe if you aren't sure what the text item delimiters are set to. As you haven't made a reference to it in your script, it should be set to an empty string, which would result in the joining of the characters back into words produce the expected result. However, this could easily not be the case, if, say, you performed the first technique of file extension castration and neglected to set the text item limiters back—then the resulting string would have a period between every single letter.
As a policy in AppleScript (which you can personally choose to adhere to or ignore), it's considered by some as poor form if you perform list to string coercion operations without first setting the text item delimiters to a definitive value.
But you needn't do so here, because rather than using characters, use text:
set myKeywords to text var1 thru var2 of myvar
You're performing a shell command that looks like this: mdls -name kMDItemKeywords <file>, and then the two lines of AppleScript that follow awkwardly try and trim off the leading and trailing parentheses around the text representation of a bash array. Instead, you can turn on the -raw flag for mdls, which simplifies the output by stripping off the name of the key for you. This then places the parentheses as the very first and very last characters; however, since there's a load of dead whitespace in the output as well, you might as well get bash to perform all the clean up for you:
mdls -raw -name kMDItemContentTypeTree <file> | grep -E -io '[^()",[:blank:]]+'
This disregards parentheses, double quotes, commas, and whitespace, so all you get back is a list of keywords, one per line, and without any extra baggage. If you needed to itemise them, you can set a variable to the paragraphs of the output from the do shell script command, which splits the text into lines placing each keyword into a list. But it seems here that you need text and don't mind it being multilinear.
When I started to write this answer, I didn't have an inkling as to what was causing the specific issue that brought you here. Having gone through the details of how mdls formats its output, I now see the issue is with the fact that the myKeywords string will contain a bunch of double quotes, and you've surrounded the placement of the myKeywords entity in your JavaScript expression with double quotes. All of these quotes are only being escaped equally and once only in the AppleScript environment but not in the JavaScript environment, which results in each neighbouring double quote acting as an open-close pair. I ran a similar command in bash to obtain an array of values (kMDContentTreeType), and then processed the text in the way AppleScript does, before opening the JavaScript console in my browser and pasting it to illustrate what's going on:
Anything in red is contained inside a string; everything else is therefore taken as a JavaScript identifier or object (or it would be if the messed up quotes didn't also mess up the syntax, and then result in an unterminated string that's still expecting one last quote to pair with.
I think the solution is to use a continuation character "\" for backward compatibility with older browsers: so you would need to have each line (except the last one) appended with a backslash, and you need to change the pair of double quotes surrounding the myKeywords value in your JavaScript expression to a pair of single quotes. In newer browsers, you can forgo the headache of appending continuation marks to each line and instead replace the pair of outside double quotes with a pair of backticks (`) instead:
❌'This line throws
an EOF error in
JavaScript';
✅'This line is \
processed successfully \
in JavaScript';
✅`This line is also
processed successfully
in JavaScript`;
I had tried the backticks ( ` ) suggested by CJK but that did not work for me. The main issue being raised was that the kMDItemKeywords returned escaped characters.
Heart,
Studio,
Red,
\"RF126-10.tif\",
Tree,
\"Heart Tree\",
occasion,
Farm,
birds,
\"Red Farm Studio\",
\"all occasion\",
all
I was able to get rid of the escaped characters using the following:
NEW CODE
set myKeywords to do shell script "echo " & quoted form of myKeywords & " | tr -d '[:cntrl:]'| tr '[:upper:]' '[:lower:]' | tr -d '\"'"
UPDATED CODE FOR JAVASCRIPT
--Inputs the Keywords from the Image Metadata--
tell application "Safari"
activate
do JavaScript "document.getElementById('ctl00_cphMainContent_txtKeyWords').value = '" & myKeywords & "';" in current tab of window 1
end tell
RESULT
--> " heart, studio, red, rf126-10.tif, tree, heart tree, occasion, farm, birds, red farm studio, all occasion, all"

file and directory regex

I am trying to create a regEx for file and directory path validation.
I have implemented this, but its failing 1 of the conditions, that it should not allow ie multiple slashes together.
Also, no other special character should not be allowed
var x = /^(\\|\/){1}([a-zA-Z0-9\s\-_\#\-\^!#$%&]*?(\\|\/)?)+(\.[a-z\/\/]+)?$/i
test 1 -> / (should pass)
test 2 -> /asdf (should pass)
test 3 -> /asdf/scd.csv (should pass)
test 4 -> //asdf (should fail, currently passing)
test 5 -> /asd/ads/c.csv/ (should pass)
test 6 -> asd/asfd/a (should fail)
Can suggestion how to solve this?
The path //asdf is valid on LINUX, UNIX, iOS, and Android, so your code already works. However, if it is important for some reason to invalidate that particular set of valid paths, simply substitute a plus sign in place of the an asterisk after the [a-z...] character group. That will cause invalidation of multiple path separators with no intervening characters.
It is probably useful to comment on larger issues with the regex approach and details.
1) You can use [\/] instead of (\|/), however both will allow false positives on every combination of operating system and file system. (Those that require forward slash should exclude backslashes as a separator and vice versa.)
2) The character range [a-zA-Z0-9\s-_\#-\^!#$%&] in the question is not the permissible character range for directory path elements for any known combination of operating system and file system. For instance, a period is valid in directory names for most.
3) Permissible character ranges are not portable. (The most reliable way to test path validation is to touch the file name on the actual file system, meaning actually instantiate an empty file and capture any indications of instantiation failure.)
4) You don't want or need a question mark after your asterisk or after your second (\|/) group. They don't create a bug, but they waste either compilation or run time, and they obfuscate your regex purpose.
5) You also need to repeat the character range just before the extension or rearrange like the example below.
6) You don't need to add the A-Z range to the a-z range if you use \i as a flag at the end of the regex.
7) It appears from the list of desired results that relative paths are to be filtered out, but there is no explicit mention of that as a rule for the solution.
With hesitation, this code is provided to demonstrate a few of the above improvements.
// This code is not production worthy
// for reasons (1) through (3) given
// above and is provided only for the
// purpose of clarifying points made.
var re = /^([\\/][a-z0-9\s\-_\#\-\^!#$%&]*)+(\.[a-z][a-z0-9]+)?$/i
console.log(
[
'/',
'/asdf',
'/asdf/scd.csv',
'//asdf',
'/asd/ads/c.csv/',
'asd/asfd/a'
].map(RegExp.prototype.test, re))
Try using /^(\/|([\\/][\w\s#^!#$%&-]+)+(\.[a-z]+[\\/]?)?)$/i instead, which forces at least one character to match between each slash:
var regex = /^(\/|([\\/][\w\s#^!#$%&-]+)+(\.[a-z]+[\\/]?)?)$/i
console.log([
'/',
'/asdf',
'/asdf/scd.csv',
'//asdf',
'/asd/ads/c.csv/',
'asd/asfd/a'
].map(RegExp.prototype.test, regex))
((\/[\w\s\.#^!#$%&-]+)+\/?)|\/[\w\.\s#^!#$%&-]*
This was tested to match your sample input,
BUT on np++ (i.e. perl-regex flavor), because I have no experience with javascript.
Therefor here the same in flavor-indpendent prose.
"(slash and character many times, followed by optional slash)
or
slash and zero or more characters".
Note1: I added explicit "." to allowed characters.
Note2: I assume your "\/" means, "explicit slash, not backslash".

Using ignorePlugin to ignore one folder from dependencies.

I've realized that one of a big folder inside one of my dependencies is not required. But since it takes almost 30kb of my build size, I wish to ignore it from the final webpack build. For that, i'm trying to use the webpack ignorePlugin.
This is what i've tried till now:
new webpack.IgnorePlugin(/^\.\/precomputed$/, /elliptic$/),
The absolute path for the folder that I wanna ignore is :
node_modules/elliptic/precomputed
What i'm doing wrong here ? Is there anything else required ? Thanks for help ! Appreciate it :)
The regular expressions you're using don't match the path of the module.
/^\.\/precomputed$/ matches only exactly ./precomputed. Because it's using the beginning of string ^ and the end of the string $, and in between is only ./precomputed.
/elliptic$/ matches every string that ends in elliitic.
The correct regular expression for your module would be:
/elliptic\/precomputed$/
But this matches only the modules that end in elliptic/precomputed (because of the $ anchor). For instance elliptic/precomputed.js or elliptic/precomputed/submodule are not matched. If you intend to include these as well you can remove the $ and it will match all of them:
/elliptic\/precomputed/
Try it in Regexr, when you add $ to the pattern you'll see that only the first one matches.

Search and replace moduleFor('foo:bar') with moduleFor('foo:bar', 'unit#foo:bar')

I am working with a large set of qunit unit tests in a folder called "tests". At the top of each file is the following, for example:
moduleFor('mixin:foo')
// or
moduleFor('route:bar')
I'd like to write a search and replace for these files such that each occurrence would be replaced with this updated style:
moduleFor('mixin:foo', 'unit#mixin:foo')
// or
moduleFor('route:bar', 'unit#route:foo')
If the first line of your file is this line, you can use this, with multiline flag on.
\AmoduleFor\('(.*?)'\)$
Where \A always matches the beginning of the input data (file in this case). $ because of the multiline flag, matches the end of the line (not the input). You can also probably remove the $ in case of following whitespace or comments you don't want to affect. If this is always the total first line, I'd leave the $.
In this example here, I deliberately use ^ to match the beginning of the line rather than the input, merely for demonstration purposes.
I'm not familiar with qunit and if there might be no other occurences of module in the file, if there is not, assertions shouldn't be necessary.

jscs error : validateLineBreaks: Invalid line break at filename.js

After grunt-jscs it gives following errors for base/index.js file.
Running "jscs:src" (jscs) task
validateLineBreaks: Invalid line break at api/v1/base/index.js :
1 |var errors = require('restify-errors');
-----------------------------------------------^
2 |function Base(Model) {
After I remove var errors = require('restify-errors'); this line, it starts giving below error
Running "jscs:src" (jscs) task
validateLineBreaks: Invalid line break at api/v1/base/index.js :
1 |function Base(Model) {
------------------------------^
How to resolve this?
Workaround found : Created new file and copied all content to it resolves the problem.
Still want to know any specific reason why this is happening?
this is probably an issue with line breaks
You might want to put "validateLineBreaks": null into your .jscsrc file
If your .jscsrs is with the rule
"validateLineBreaks":"LF",
It means you must use LF as line breaks, if you are using other line break symbol (such as CRLF), JSCS will give you an error like:
validateLineBreaks: Invalid line break at api/v1/base/index.js :
There're two ways to resolve the problem, one is to change the jscs' rule, and the other is to always use LF as line breaks.
You can find the different between LF and CR in this link:
https://en.wikipedia.org/wiki/Newline
tldr;
Change between LF an CRLF, if you are using VScode you can do this by clicking the option at the bottom right:
Detailed: As tomato said, the issue is probably that the line break format of your IDE isn't compatible with jscs, from the eslint documentation:
The linebreaks (new lines) used in windows operating system are
usually carriage returns (CR) followed by a line feed (LF) making it a
carriage return line feed (CRLF) whereas Linux and Unix use a simple
line feed (LF). The corresponding control sequences are "\n" (for LF)
and "\r\n" for (CRLF)
You can also try adding *.js text eol=lf to your .gitattributes file if you know this won't affect the project in any meaningful way.
You can read more about the issue here: https://eslint.org/docs/rules/linebreak-style

Categories

Resources