Script to remove extra spaces in text blocks?

New Here ,
Jul 31, 2022 Jul 31, 2022

Copy link to clipboard

Copied

Is there a script to be able to remove extra spaces (and soft returns) within a text block in photoshop?

And if so, how would I load the script again? I remember there's a folders somewhere I need to put the script file into? Then it shows up under the fle menu, under automations, right. 


TOPICS
Actions and scripting , macOS

Views

190

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Adobe Community Professional , Aug 05, 2022 Aug 05, 2022

@NDL_DH – Yes, as I previously wrote I don't know why the formatting is lost or how to avoid that. More accomplished scripters may be able to answer.

 

You can use the Edit > Find and Replace Text command. ScriptingListener can also capture the use of this as well and it doesn't remove the formatting in my simple tests.

 

The issue is that it uses strings as input/output, I can't work out how to "inject" variables or regular expressions. Therefore it would need repetition with hard-coded values:

...

Likes

Translate

Translate
New Here ,
Jul 31, 2022 Jul 31, 2022

Copy link to clipboard

Copied

..I have a InDesign script that use to remove extra spacces, posted below.
Making a photoshop version of the below would be a good start..?

 

//reset GREP preferences
app.findGrepPreferences=app.changeGrepPreferences=null;


app.findGrepPreferences.findWhat="[~m~>~f~|~S~s~<~/~.~3~4~% ]{2,}";



app.changeGrepPreferences.changeTo="\\s";


 
var sel = app.selection;  
    for(var n=0;n<sel.length;n++)  
    {  
        sel[n].changeGrep();  
    };  


//reset GREP preferences
//app.findGrepPreferences=app.changeGrepPreferences=null;

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jul 31, 2022 Jul 31, 2022

Copy link to clipboard

Copied

EDIT:
..I have an InDesign script that I use to remove extra spacces, posted below.

Making a photoshop version of the below script would be a good start..?

//reset GREP preferences
app.findGrepPreferences=app.changeGrepPreferences=null;


app.findGrepPreferences.findWhat="[~m~>~f~|~S~s~<~/~.~3~4~% ]{2,}";



app.changeGrepPreferences.changeTo="\\s";


 
var sel = app.selection;  
    for(var n=0;n<sel.length;n++)  
    {  
        sel[n].changeGrep();  
    };  


//reset GREP preferences
//app.findGrepPreferences=app.changeGrepPreferences=null;

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

@NDL_DH 

 

The following script will replace 1 or more word spaces with a single word space in the active document:

 

var doc = app.activeDocument;
for (var j = 0; j < doc.layers.length; j++) {
    try {
        doc.activeLayer = doc.layers[j];
        if (app.activeDocument.activeLayer.kind == LayerKind.TEXT) {
            doc.activeLayer.textItem.contents = doc.activeLayer.textItem.contents.replace(/ +/g, ' ');
        }
    } catch (e) {}
}

 

I am not sure if Photoshop has the same level of support as one would find in InDesign, I can't get a soft return (shift + return)  to work:

 

.replace(/\u2029/g, '')

 

Edit: Instructions for saving and installing script code here –

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

Wow, thanks so much for this.

Just waiting for my admin at work to place it in the scripts folder.

Will report back results and mark correct hopefully by tomorrow.

Just to be clear though, this script I can run while having a text box selected (or the actual text selected, i.e., with the type tool) and it will only effect what I have selected, right?

Just want to make sure it's not going to effect everything within the PSD, regardless if it's selected or not. That would be bad.  

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

It edits alll text layers in the open doc.

 

Remove the for loop to only edit the active layer.

 

The script can also be browsed without installation.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied


@Stephen_A_Marsh wrote:

It edits alll text layers in the open doc.

 

Remove the for loop to only edit the active layer.

 

The script can also be browsed without installation.


 

...So would something like the below work, where I commmented out the "for" line, and the closing "}" also?

var doc = app.activeDocument;
/* for (var j = 0; j < doc.layers.length; j++) {  */
    try {
        doc.activeLayer = doc.layers[j];
        if (app.activeDocument.activeLayer.kind == LayerKind.TEXT) {
            doc.activeLayer.textItem.contents = doc.activeLayer.textItem.contents.replace(/ +/g, ' ');
        }
    } catch (e) {}
/* }  */

 

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied


@Stephen_A_Marsh wrote:

It edits alll text layers in the open doc.

 

Remove the for loop to only edit the active layer.

 

The script can also be browsed without installation.


...Oh, duh, it can be browsed, let me see if I can test it now. 🤦🏾‍:male_sign:

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

I tried removing the "for" loop, and the"try" line also, cause that's a part of the loop also, right. Both resulted in errors.

Then it was throwing errors because of the "j" inside of doc.layers[j];, so I deleted the "j" from there, and still nothing, just more errors.

var doc = app.activeDocument;
// for (var j = 0; j < doc.layers.length; j++) {  
//    try {
        doc.activeLayer = doc.layers[];
        if (app.activeDocument.activeLayer.kind == LayerKind.TEXT) {
            doc.activeLayer.textItem.contents = doc.activeLayer.textItem.contents.replace(/ +/g, ' ');
        }
 //   } catch (e) {}
 //} 

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

2 things:

1. I went back to the original script, and nothing happens when I run that also, but it doesn't give an errors either.

2. I ran the below, and it didn't remove the spaces, but it removed all the formatting on the box I had selected, defaulting it to the fontsize and color, etc, of the top most line, i.e., the headline. But it also threw no errors. 

var doc = app.activeDocument;

        if (app.activeDocument.activeLayer.kind == LayerKind.TEXT) {
            doc.activeLayer.textItem.contents = doc.activeLayer.textItem.contents.replace(/ +/g, ' ');
        }

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

That's alright, in re to the soft return.

I'll be more than happy if this word space script works. 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

And if so, how would I load the script again? I remember there's a folders somewhere I need to put the script file into? 

Presets > Scripts 

Screenshot 2022-08-01 at 12.55.38.png

 

In the program they are listed under File > Scripts 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

Yes, thanks for showing me the location, found it.

Cheers.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

@Stephen_A_Marsh This script below, removes the spaces from the selected text layer, but it also removes all the formating, and defaults to the headline styling (font weight, size, color, etc).

Is there a way to retain the existing styling? 


 

var doc = app.activeDocument;

        app.activeDocument.activeLayer.kind == LayerKind.TEXT ;

            doc.activeLayer.textItem.contents = doc.activeLayer.textItem.contents.replace(/ +/g, ' ');
        

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

That is unexpected, I didn't intend for the formatting to be removed, however, you are indeed correct.

 

This is what I was referring to with regards to removing the for loop:

 

var doc = app.activeDocument;
try {
    if (doc.activeLayer.kind == LayerKind.TEXT) {
        doc.activeLayer.textItem.contents = doc.activeLayer.textItem.contents.replace(/ +/g, ' ');
    }
} catch (e) {}

 

I'm not sure why this would affect the formatting, however, I don't have a great deal of experience with scripting text layer changes so it may be something basic.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 05, 2022 Aug 05, 2022

Copy link to clipboard

Copied

This removes the spaces, but defaults the styling to whatever the top most style is, like previously mentioned.

It's so close I can taste it.

Monday I'll try to look for something that retains styling, that maybe I can place at the end of this script, IDK...?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

@Stephen_A_Marsh Also, sorry for all these messages, but is there a way to remove a space and an adjoining return or soft return..?
Along with the multiple space, or a separate jsx to deal with occurances of space followed by a return or soft return..?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied


@NDL_DH wrote:

@Stephen_A_Marsh Also, sorry for all these messages, but is there a way to remove a space and an adjoining return or soft return..?
Along with the multiple space, or a separate jsx to deal with occurances of space followed by a return or soft return..?


 

As I wrote earlier, I can't see a way to change a soft-return.

 

Multiple spaces and or multiple spaces and a line ending to be replaced with a space would be:

 

var doc = app.activeDocument;
try {
    if (doc.activeLayer.kind == LayerKind.TEXT) {
        doc.activeLayer.textItem.contents = doc.activeLayer.textItem.contents.replace(/ +\r/g, ' ');
    }
} catch (e) {}

 

I'm not sure why this would affect the formatting, however, I don't have a great deal of experience with scripting text layer changes so it may be something basic.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 04, 2022 Aug 04, 2022

Copy link to clipboard

Copied

I'll test this out tomorrow and post results. 

Thanks again. 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 05, 2022 Aug 05, 2022

Copy link to clipboard

Copied

This works too, but removes the styling also, defaulting to the topmost style on the text layer.


Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 05, 2022 Aug 05, 2022

Copy link to clipboard

Copied

@Stephen_A_Marsh I wonder if anything on this thread will work, to retain styling after script runs?
https://community.adobe.com/t5/photoshop-ecosystem-discussions/setting-a-font-on-a-psd-text-item-in-... 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 05, 2022 Aug 05, 2022

Copy link to clipboard

Copied

@Stephen_A_Marsh 
@c.pfaffenbichler 
I get the same results using this, below.
Removes extra spaces but the styling still defaults.


/*
var doc = app.activeDocument;
try {
    if (doc.activeLayer.kind == LayerKind.TEXT) {
        doc.activeLayer.textItem.contents = doc.activeLayer.textItem.contents.replace(/ +/g, ' ');
    }
} catch (e) {}
*/


var aLay = app.activeDocument.activeLayer;
try{
if(aLay.textItem && aLay.textItem.contents != "") {


var changedText= aLay.textItem.contents.replace (/ +/g, ' ');

aLay.textItem.contents = changedText;

} 
} catch (e) {}

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Aug 05, 2022 Aug 05, 2022

Copy link to clipboard

Copied

@NDL_DH – Yes, as I previously wrote I don't know why the formatting is lost or how to avoid that. More accomplished scripters may be able to answer.

 

You can use the Edit > Find and Replace Text command. ScriptingListener can also capture the use of this as well and it doesn't remove the formatting in my simple tests.

 

The issue is that it uses strings as input/output, I can't work out how to "inject" variables or regular expressions. Therefore it would need repetition with hard-coded values: find/replace two spaces with one space. Repeat again for three spaces and replace with one space etc. Not the end of the world, but it could be better...

 

Edit:

 

findReplaceText("  ", " ", true, false, false, false, false); // 2 spaces
findReplaceText("   ", " ", true, false, false, false, false); // 3 spaces
findReplaceText("    ", " ", true, false, false, false, false); // 4 spaces
findReplaceText("     ", " ", true, false, false, false, false); // 5 spaces

function findReplaceText(find, replace, checkAll, forward, caseSensitive, wholeWord, ignoreAccents) {
	function s2t(s) {
        return app.stringIDToTypeID(s);
    }
	var descriptor = new ActionDescriptor();
	var descriptor2 = new ActionDescriptor();
	var reference = new ActionReference();
	reference.putProperty( s2t( "property" ), s2t( "replace" ));
	reference.putEnumerated( s2t( "textLayer" ), s2t( "ordinal" ), s2t( "allEnum" ));
	descriptor.putReference( s2t( "null" ), reference );
	descriptor2.putString( s2t( "find" ), find );
	descriptor2.putString( s2t( "replace" ), replace );
	descriptor2.putBoolean( s2t( "checkAll" ), checkAll );
	descriptor2.putBoolean( s2t( "forward" ), forward );
	descriptor2.putBoolean( s2t( "caseSensitive" ), caseSensitive );
	descriptor2.putBoolean( s2t( "wholeWord" ), wholeWord );
	descriptor2.putBoolean( s2t( "ignoreAccents" ), ignoreAccents );
	descriptor.putObject( s2t( "using" ), s2t( "findReplace" ), descriptor2 );
	executeAction( s2t( "replace" ), descriptor, DialogModes.NO );
}

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Aug 06, 2022 Aug 06, 2022

Copy link to clipboard

Copied

I guess repeating the replacement of double-spaces until there are none would suffice. 

 

DOM-support for Type Layers is not great unfortunately and, as you are probably aware, editing them via AM-code is a bit »peculiar«. Not impossible but, for me at least, not exactly comfortable. 

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Aug 06, 2022 Aug 06, 2022

Copy link to clipboard

Copied

Something peculiar seems to prevent this Script from running meaningfully in specific situations, but try it anyway: 

(edited 2022-08-07)

 

// 2022, use it at your own risk;
if (app.documents.length > 0) {
    var theTypeLayers = collectTypeLayersTexts();
    selectLayerByID(theTypeLayers[0][2]);
    var theCheck = false;
    for (var n = 0; n < theTypeLayers.length; n ++) {
        if (theTypeLayers[n][4].indexOf("  ") != -1) {theCheck = true}
    };
    while (theCheck == true) {
        replaceText ("  ", " ");
        var theTypeLayers = collectTypeLayersTexts();
        var theCheck = false;
        for (var m = 0; m < theTypeLayers.length; m ++) {
            if (theTypeLayers[m][4].indexOf("  ") != -1) {theCheck = true}
        };
    };
};
////// reoplace text //////
function replaceText (replaceThis, replaceWith) {
try {
// =======================================================
var idreplace = stringIDToTypeID( "replace" );
    var desc22 = new ActionDescriptor();
    var idnull = charIDToTypeID( "null" );
        var ref3 = new ActionReference();
        var idPrpr = charIDToTypeID( "Prpr" );
        var idreplace = stringIDToTypeID( "replace" );
        ref3.putProperty( idPrpr, idreplace );
        var idTxLr = charIDToTypeID( "TxLr" );
        var idOrdn = charIDToTypeID( "Ordn" );
        var idAl = charIDToTypeID( "Al  " );
        ref3.putEnumerated( idTxLr, idOrdn, idAl );
    desc22.putReference( idnull, ref3 );
    var idUsng = charIDToTypeID( "Usng" );
        var desc23 = new ActionDescriptor();
        var idfind = stringIDToTypeID( "find" );
        desc23.putString( idfind, replaceThis );
        var idreplace = stringIDToTypeID( "replace" );
        desc23.putString( idreplace, replaceWith );
        var idcheckAll = stringIDToTypeID( "checkAll" );
        desc23.putBoolean( idcheckAll, true );
        var idFwd = charIDToTypeID( "Fwd " );
        desc23.putBoolean( idFwd, true );
        var idcaseSensitive = stringIDToTypeID( "caseSensitive" );
        desc23.putBoolean( idcaseSensitive, false );
        var idwholeWord = stringIDToTypeID( "wholeWord" );
        desc23.putBoolean( idwholeWord, false );
        var idignoreAccents = stringIDToTypeID( "ignoreAccents" );
        desc23.putBoolean( idignoreAccents, true );
    var idfindReplace = stringIDToTypeID( "findReplace" );
    desc22.putObject( idUsng, idfindReplace, desc23 );
executeAction( idreplace, desc22, DialogModes.NO );
} catch (e) {}
};
////// collect layers //////
function collectTypeLayersTexts () {
// get number of layers;
    var ref = new ActionReference();
    ref.putProperty(stringIDToTypeID('property'), stringIDToTypeID('numberOfLayers'));
    ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
    var applicationDesc = executeActionGet(ref);
    var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
    var theLayers = new Array;
    for (var m = 0; m <= theNumber; m++) {
    try {
    var ref = new ActionReference();
    ref.putIndex( charIDToTypeID( "Lyr " ), m);
    var layerDesc = executeActionGet(ref);
    var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
    var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if type layer collect values;
    if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true && layerDesc.hasKey(stringIDToTypeID("textKey")) == true) {
    var theName = layerDesc.getString(stringIDToTypeID('name'));
    var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
    var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
    var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
    var theseBounds = [theBounds.getUnitDoubleValue(stringIDToTypeID("left")), theBounds.getUnitDoubleValue(stringIDToTypeID("top")), theBounds.getUnitDoubleValue(stringIDToTypeID("right")), theBounds.getUnitDoubleValue(stringIDToTypeID("bottom"))];
    var textDesc = layerDesc.getObjectValue(stringIDToTypeID('textKey'));
    var theText = textDesc.getString(stringIDToTypeID("textKey"));
    theLayers.push([theName, theIndex, theID, theseBounds, theText])
    };
    }
    catch (e) {};
    };
    return theLayers
    };
////// based on code by mike hale and paul riggott //////
function selectLayerByID(index,add){ 
    add = undefined ? add = false:add 
    var ref = new ActionReference();
        ref.putIdentifier(charIDToTypeID("Lyr "), index);
        var desc = new ActionDescriptor();
        desc.putReference(charIDToTypeID("null"), ref );
           if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) ); 
          desc.putBoolean( charIDToTypeID( "MkVs" ), false ); 
       try{
        executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
    }catch(e){
    alert(e.message); 
    }
    };

 

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines