• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Automatic sub header styling script help

Contributor ,
Jul 04, 2024 Jul 04, 2024

Copy link to clipboard

Copied

Hello 

I have a script which is suppose to find subheads and change them applying text settings a user has predefined. For example a user writes at the very top of the text box 'test' applies all styles they want, then selects the text box, and when the script is run it will go through the text and apply the same text settings as the word 'test' to all subheaders. 

The below I outline a working script which looks for the first instance of the word 'test', reads text settings, and applies it to other instances of text. 

When I then experimented to change it so that it looks for the first instance of the word 'text. reads text settings, and applies those settings to subheaders I ran into issues. 

In particutlar subheaders can be idenified as -

- has at least two hard enter returns or more (one for the termination of the paragraph above, one for a line space)
- then a string comprising of under 6 words (normally they are short so let's say 6 for now)
- this string must not have a full stop '.'

When I try to run the script which should be able to apply text stylings for subheaders it says it cannot find any... but there are

Okay here is the 1st working part which the scripts reads the word and applies those text settings to the same word 

// Adobe InDesign ExtendScript

// Function to find "test" as a standalone word in selected text frame and apply its text settings to other paragraphs
function findAndApplyTextSettings() {
var doc = app.activeDocument;
var textFrame = app.selection[0]; // Get selected text frame

if (textFrame instanceof TextFrame) {
var paragraphs = textFrame.paragraphs;
var foundTest = false;
var testTextSettings;

// Define RegExp to match "test" as a standalone word
var testRegex = /\btest\b/i;

// First, find the paragraph containing standalone "test" and get its text settings
for (var i = 0; i < paragraphs.length; i++) {
var paragraph = paragraphs[i];

// Check if the paragraph contains standalone "test"
if (testRegex.test(paragraph.contents)) {
// Found standalone "test" in this paragraph, get text settings
var testWord = paragraph.words.itemByRange(0, paragraph.words.length-1).getElements()[0]; // Get first word "test"
testTextSettings = {
appliedFont: testWord.appliedFont,
pointSize: testWord.pointSize,
fillColor: testWord.fillColor,
justification: paragraph.justification // Get text alignment (justification)
// Add more text attributes as needed
};
foundTest = true;
break; // Exit loop once found
}
}

if (foundTest) {
// Apply "test" text settings to all text in the text frame within an undoable action
app.doScript(function() {
for (var j = 0; j < paragraphs.length; j++) {
var para = paragraphs[j];

// Apply text settings only if it's not the "test" paragraph itself
if (!testRegex.test(para.contents)) {
var words = para.words.everyItem().getElements();
for (var k = 0; k < words.length; k++) {
words[k].appliedFont = testTextSettings.appliedFont;
words[k].pointSize = testTextSettings.pointSize;
words[k].fillColor = testTextSettings.fillColor;
para.justification = testTextSettings.justification;
// Add more text attributes as needed
}
}
}
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Apply 'test' Text Settings");

alert("Applied text settings (including alignment) from 'test' word to all other text in the selected text frame.");
} else {
alert("No standalone 'test' word found in the selected text frame.");
}
} else {
alert("Please select a text frame.");
}
}

// Run the function
findAndApplyTextSettings();

 

 

 

 

 

 

And here is the script which tries to find subheaders but doesnt work  - it runs minus error but says there are no subheaders 



 

// Adobe InDesign ExtendScript

// Function to find subheaders and apply text settings based on the first instance
function findAndApplySubheaderSettings() {
var doc = app.activeDocument;
var textFrame = app.selection[0]; // Get selected text frame

if (textFrame instanceof TextFrame) {
var paragraphs = textFrame.paragraphs;
var foundSubheader = false;
var subheaderTextSettings;

// Define criteria for identifying subheaders
var subheaderRegex = /^([^\r\n]+[\r\n]){2,}([^\r\n]{1,}\s){1,5}[^\.\r\n]+$/;

// First, find the paragraph containing a subheader and get its text settings
for (var i = 0; i < paragraphs.length; i++) {
var paragraph = paragraphs[i];

// Check if the paragraph matches the subheader criteria
if (subheaderRegex.test(paragraph.contents)) {
// Found subheader matching criteria, get text settings
subheaderTextSettings = {
appliedFont: paragraph.words[0].appliedFont,
pointSize: paragraph.words[0].pointSize,
fillColor: paragraph.words[0].fillColor,
justification: paragraph.justification
// Add more text attributes as needed
};
foundSubheader = true;
break; // Exit loop once found
}
}

if (foundSubheader) {
// Apply subheader text settings to all subheaders in the text frame within an undoable action
app.doScript(function() {
for (var j = 0; j < paragraphs.length; j++) {
var para = paragraphs[j];

// Apply text settings only if it matches the subheader criteria
if (subheaderRegex.test(para.contents)) {
var words = para.words.everyItem().getElements();
for (var k = 0; k < words.length; k++) {
words[k].appliedFont = subheaderTextSettings.appliedFont;
words[k].pointSize = subheaderTextSettings.pointSize;
words[k].fillColor = subheaderTextSettings.fillColor;
para.justification = subheaderTextSettings.justification;
// Add more text attributes as needed
}
}
}
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Apply Subheader Text Settings");

alert("Applied text settings (including alignment) from the first subheader to all other subheaders in the selected text frame.");
} else {
alert("No subheader found in the selected text frame matching the criteria.");
}
} else {
alert("Please select a text frame.");
}
}

// Run the function
findAndApplySubheaderSettings();

 

SmythWharf_0-1720133856108.png

 

 

 

Any ideas would be amazing. 

Many regards, 

Smyth 

 

 

TOPICS
Experiment , How to , Scripting , SDK , UXP Scripting

Views

352

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

Community Expert , Jul 05, 2024 Jul 05, 2024

 any ideas on how one could indentify 6 or fewer word paragraphs?

 

if (myParagraph.words.length <= 6) {
  // ...
}

Votes

Translate

Translate
Community Expert ,
Jul 04, 2024 Jul 04, 2024

Copy link to clipboard

Copied

para.contents can have only ONE "\r\n" - at the end.

 

Votes

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
Contributor ,
Jul 05, 2024 Jul 05, 2024

Copy link to clipboard

Copied

Hello, 

Thank you for looking. 

I had a go but no luck. I did manage to make a basic script which was able to check for returns with conditions for example 2 returns in a row or more etc 

then I tried to make a simple script to check for instances in which there were 6 or less words before another paragraph this part I had difficutly with. 

I think perhaps this is the part which is most difficult, any ideas on how one could indentify 6 or less word paragraphs?

 

Thanks 

 

Smyth

Votes

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
Community Expert ,
Jul 05, 2024 Jul 05, 2024

Copy link to clipboard

Copied

I'm not GREP expert - and I can't check it right now - but you could start with something like this:

 

\r\r[\w\s]{1,6}

 

You might need to include ".,:;'" etc. 

 

And instead of going through paragraphs collection of the TextFrame - or parent Story - you should use find() and then iterate through results.

 

Unfortunately, I'm not JS guy so can't give you working code either. 

 

But if you Google - you'll find examples that you should be able to piece together. 

 

Votes

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
Community Expert ,
Jul 05, 2024 Jul 05, 2024

Copy link to clipboard

Copied

Please place your code in a code box (use </> from the toolbox at the top of the message window). People might then in fact read the code ratherthan just glance through it.

 

To find the first instance of a test word, use InDesign's GREP, not JavaScript's -- it's much easier to code and probably quicker too.

 

Instead of reading/applying overrides, why don't you use a paragraph and/or a character style? Makes life really easy.

 

 

Votes

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
Contributor ,
Jul 05, 2024 Jul 05, 2024

Copy link to clipboard

Copied

Apologies I was having difficulties with the insert not deleting itself - I normally do post the mark up code. 


The paragraph styles and characters styles are not useful as in my case there is no standard for subhead design so an adaptive means to which a key word is styled as I would like and then applied throughout would be the most useful. 
As subheaders are varied in that it could be anything words, numbers etc it would be unfessable to wade through the copy and them out and use find and replace using the style function. 
The goal is a script which can apply a subheader using a style which has been designed as a once off  for that document - and therefore does not need to be indexed as a style - as it would not be a house style but a personal choice of a style 
I will have a look at the suggestions. As a non coder I get stuck on these things easily. 
Best, 
Smyth

Votes

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
Community Expert ,
Jul 05, 2024 Jul 05, 2024

Copy link to clipboard

Copied

 any ideas on how one could indentify 6 or fewer word paragraphs?

 

if (myParagraph.words.length <= 6) {
  // ...
}

Votes

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
Contributor ,
Jul 05, 2024 Jul 05, 2024

Copy link to clipboard

Copied

Hello,

 

Thank you for your advice. It was enough for me to figure simpler logic.

 

This script automates the styling of subheaders which have less than 10 words in length and no period '.' It does this by picking up the text settings of the first instance of the word 'test' (this will later change)

 

Below I have a preliminary proof of concept script. I will add more text settings to it which will make it more useful.

 

 

 

 

// Function to find "test" as a standalone word in selected text frame and apply its text settings to specific paragraphs
function findAndApplyTextSettings() {
    // Ensure that there's an active document open
    if (app.documents.length > 0) {
        var doc = app.activeDocument;
        var selection = app.selection;

        if (selection.length > 0 && selection[0] instanceof TextFrame) {
            var selectedTextFrames = selection;
            var foundTest = false;
            var testTextSettings;
            var testRegex = /\btest\b/i;

            // Iterate over each selected text frame
            for (var j = 0; j < selectedTextFrames.length; j++) {
                var paragraphs = selectedTextFrames[j].parentStory.paragraphs.everyItem().getElements();

                // First, find the paragraph containing standalone "test" and get its text settings
                for (var i = 0; i < paragraphs.length; i++) {
                    var paragraph = paragraphs[i];

                    // Check if the paragraph contains standalone "test"
                    if (testRegex.test(paragraph.contents)) {
                        // Found standalone "test" in this paragraph, get text settings
                        var testWord = paragraph.words.itemByRange(0, paragraph.words.length - 1).getElements()[0];
                        testTextSettings = {
                            appliedFont: testWord.appliedFont,
                            pointSize: testWord.pointSize,
                            fillColor: testWord.fillColor,
                            justification: paragraph.justification // Get text alignment (justification)
                            // Add more text attributes as needed
                        };
                        foundTest = true;
                        break; // Exit loop once found
                    }
                }

                if (foundTest) {
                    // Apply "test" text settings to specific paragraphs in the text frame within an undoable action
                    app.doScript(function() {
                        for (var i = 0; i < paragraphs.length; i++) {
                            var para = paragraphs[i];
                            var words = para.words.length;
                            var paragraphText = para.contents;

                            // Apply text settings only if it's not the "test" paragraph itself
                            // and it has fewer than 10 words and no full stop
                            if (!testRegex.test(para.contents) && words < 11 && paragraphText.indexOf('.') === -1) {
                                var paraWords = para.words.everyItem().getElements();
                                for (var k = 0; k < paraWords.length; k++) {
                                    paraWords[k].appliedFont = testTextSettings.appliedFont;
                                    paraWords[k].pointSize = testTextSettings.pointSize;
                                    paraWords[k].fillColor = testTextSettings.fillColor;
                                }
                                para.justification = testTextSettings.justification;
                                // Add more text attributes as needed
                            }
                        }
                    }, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Apply 'test' Text Settings");
                } else {
                    alert("No standalone 'test' word found in the selected text frame.");
                }
            }
        } else {
            alert("Please select a text frame.");
        }
    } else {
        alert("No active document found.");
    }
}

// Run the function
findAndApplyTextSettings();

 

 

 

Here is some text from wikipedia and I added in some subheaders - leading is poor as it is not in the script yet

 

Before

SmythWharf_0-1720218043443.png

Step where the user puts in their chosen settings 

SmythWharf_2-1720218649686.png

Step where used has used the script

SmythWharf_3-1720218688587.png

 

 

 

 

Votes

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
Contributor ,
Jul 05, 2024 Jul 05, 2024

Copy link to clipboard

Copied

I will above date the above shortly 

Votes

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
Contributor ,
Jul 06, 2024 Jul 06, 2024

Copy link to clipboard

Copied

LATEST

Hello 

 

the below version allows the user to type subhead at the start of the copy in a text frame  - they can either come up with their own style or use a paragraph style to adjust the word subheader to their liking. 

 

Once adjusted they can run the script and all subheads shorter than 10 words but containing at least a word and no full stop will be changed.

 

later editions of this script will allow for multi subheads for example, line 1 location, line 2 house price, line 3 age of buyer in this instance there are three subheaders not just one etc

 

anyway for now the script below might be useful 

 

function findAndApplyTextSettings() {
    // Ensure that there's an active document open
    if (app.documents.length > 0) {
        var doc = app.activeDocument;
        var selection = app.selection;

        // Ensure there's a valid selection
        if (selection.length > 0 && (selection[0] instanceof TextFrame || selection[0].hasOwnProperty('insertionPoints'))) {
            var selectedTextFrames = [];
            if (selection[0] instanceof TextFrame) {
                selectedTextFrames.push(selection[0]);
            } else if (selection[0].hasOwnProperty('insertionPoints')) {
                selectedTextFrames.push(selection[0].parentTextFrames[0]);
            }

            var foundSubHead = false;
            var subHeadTextSettings;
            var subHeadRegex = /\bsubhead\b/i;

            // Define capitalization constants
            var capitalizationSettings = {
                ALL_CAPS: 1634493296,
                CAP_TO_SMALL_CAP: 1664250723,
                NORMAL: 1852797549,
                SMALL_CAPS: 1936548720,
                RULE_ABOVE: 1919251315, // Constant for ruleAbove setting
                RULE_BELOW: 1919251316  // Constant for ruleBelow setting
            };

            // Iterate over each selected text frame
            for (var j = 0; j < selectedTextFrames.length; j++) {
                var paragraphs = selectedTextFrames[j].parentStory.paragraphs.everyItem().getElements();

                // First, find the paragraph containing standalone "sub head" and get its text settings
                for (var i = 0; i < paragraphs.length; i++) {
                    var paragraph = paragraphs[i];

                    // Check if the paragraph contains standalone "sub head"
                    if (subHeadRegex.test(paragraph.contents)) {
                        // Found standalone "sub head" in this paragraph, get text settings
                        var subHeadPhrase = paragraph.words.itemByRange(0, paragraph.words.length - 1).getElements()[0];
                        subHeadTextSettings = {
                            appliedFont: subHeadPhrase.appliedFont,
                            pointSize: subHeadPhrase.pointSize,
                            fillColor: subHeadPhrase.fillColor,
                            justification: paragraph.justification,
                            leading: paragraph.leading,
                            firstLineIndent: paragraph.firstLineIndent,
                            baselineShift: subHeadPhrase.baselineShift,
                            tracking: subHeadPhrase.tracking,
                            capitalization: getCapitalization(subHeadPhrase.capitalization),
                            alignToBaseline: subHeadPhrase.alignToBaseline,
                            ruleAbove: paragraph.ruleAbove === true,
                            ruleBelow: paragraph.ruleBelow === true,
                            ruleAboveColor: paragraph.ruleAboveColor,
                            ruleAboveGapColor: paragraph.ruleAboveGapColor,
                            ruleAboveGapOverprint: paragraph.ruleAboveGapOverprint === true,
                            ruleAboveGapTint: paragraph.ruleAboveGapTint,
                            ruleAboveLeftIndent: paragraph.ruleAboveLeftIndent,
                            ruleAboveLineWeight: paragraph.ruleAboveLineWeight,
                            ruleAboveOffset: paragraph.ruleAboveOffset,
                            ruleAboveOverprint: paragraph.ruleAboveOverprint === true,
                            ruleAboveRightIndent: paragraph.ruleAboveRightIndent,
                            ruleAboveTint: paragraph.ruleAboveTint,
                            ruleAboveType: paragraph.ruleAboveType,
                            ruleAboveWidth: paragraph.ruleAboveWidth,
                            ruleBelowColor: paragraph.ruleBelowColor,
                            ruleBelowGapColor: paragraph.ruleBelowGapColor,
                            ruleBelowGapOverprint: paragraph.ruleBelowGapOverprint === true,
                            ruleBelowGapTint: paragraph.ruleBelowGapTint,
                            ruleBelowLeftIndent: paragraph.ruleBelowLeftIndent,
                            ruleBelowLineWeight: paragraph.ruleBelowLineWeight,
                            ruleBelowOffset: paragraph.ruleBelowOffset,
                            ruleBelowOverprint: paragraph.ruleBelowOverprint === true,
                            ruleBelowRightIndent: paragraph.ruleBelowRightIndent,
                            ruleBelowTint: paragraph.ruleBelowTint,
                            ruleBelowType: paragraph.ruleBelowType,
                            ruleBelowWidth: paragraph.ruleBelowWidth
                            // Add more text attributes as needed
                        };
                        foundSubHead = true;
                        break; // Exit loop once found
                    }
                }

                if (foundSubHead) {
                    // Apply "sub head" text settings to specific paragraphs in the text frame within an undoable action
                    app.doScript(function() {
                        for (var i = 0; i < paragraphs.length; i++) {
                            var para = paragraphs[i];
                            var words = para.words.length;
                            var paragraphText = para.contents;

                            // Apply text settings only if it's not the "sub head" paragraph itself
                            // and it has fewer than 10 words but at least 1 word and no full stop
                            if (!subHeadRegex.test(para.contents) && words > 0 && words < 10 && paragraphText.indexOf('.') === -1) {
                                // Apply paragraph-level settings
                                para.appliedFont = subHeadTextSettings.appliedFont;
                                para.pointSize = subHeadTextSettings.pointSize;
                                para.fillColor = subHeadTextSettings.fillColor;
                                para.leading = subHeadTextSettings.leading;
                                para.firstLineIndent = subHeadTextSettings.firstLineIndent;
                                para.justification = subHeadTextSettings.justification;
                                para.ruleAbove = subHeadTextSettings.ruleAbove;
                                para.ruleAboveColor = subHeadTextSettings.ruleAboveColor;
                                para.ruleAboveGapColor = subHeadTextSettings.ruleAboveGapColor;
                                para.ruleAboveGapOverprint = subHeadTextSettings.ruleAboveGapOverprint;
                                para.ruleAboveGapTint = subHeadTextSettings.ruleAboveGapTint;
                                para.ruleAboveLeftIndent = subHeadTextSettings.ruleAboveLeftIndent;
                                para.ruleAboveLineWeight = subHeadTextSettings.ruleAboveLineWeight;
                                para.ruleAboveOffset = subHeadTextSettings.ruleAboveOffset;
                                para.ruleAboveOverprint = subHeadTextSettings.ruleAboveOverprint;
                                para.ruleAboveRightIndent = subHeadTextSettings.ruleAboveRightIndent;
                                para.ruleAboveTint = subHeadTextSettings.ruleAboveTint;
                                para.ruleAboveType = subHeadTextSettings.ruleAboveType;
                                para.ruleAboveWidth = subHeadTextSettings.ruleAboveWidth;
                                para.ruleBelow = subHeadTextSettings.ruleBelow;
                                para.ruleBelowColor = subHeadTextSettings.ruleBelowColor;
                                para.ruleBelowGapColor = subHeadTextSettings.ruleBelowGapColor;
                                para.ruleBelowGapOverprint = subHeadTextSettings.ruleBelowGapOverprint;
                                para.ruleBelowGapTint = subHeadTextSettings.ruleBelowGapTint;
                                para.ruleBelowLeftIndent = subHeadTextSettings.ruleBelowLeftIndent;
                                para.ruleBelowLineWeight = subHeadTextSettings.ruleBelowLineWeight;
                                para.ruleBelowOffset = subHeadTextSettings.ruleBelowOffset;
                                para.ruleBelowOverprint = subHeadTextSettings.ruleBelowOverprint;
                                para.ruleBelowRightIndent = subHeadTextSettings.ruleBelowRightIndent;
                                para.ruleBelowTint = subHeadTextSettings.ruleBelowTint;
                                para.ruleBelowType = subHeadTextSettings.ruleBelowType;
                                para.ruleBelowWidth = subHeadTextSettings.ruleBelowWidth;

                                // Apply word-level settings to each word in the paragraph
                                var paraWords = para.words.everyItem().getElements();
                                for (var k = 0; k < paraWords.length; k++) {
                                    paraWords[k].appliedFont = subHeadTextSettings.appliedFont;
                                    paraWords[k].pointSize = subHeadTextSettings.pointSize;
                                    paraWords[k].fillColor = subHeadTextSettings.fillColor;
                                    paraWords[k].leading = subHeadTextSettings.leading;
                                    paraWords[k].baselineShift = subHeadTextSettings.baselineShift;
                                    paraWords[k].tracking = subHeadTextSettings.tracking;
                                    paraWords[k].capitalization = subHeadTextSettings.capitalization;
                                    paraWords[k].alignToBaseline = subHeadTextSettings.alignToBaseline;
                                    // Apply other text attributes as needed
                                }
                            }
                        }
                    }, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Apply 'sub head' Text Settings");
                } else {
                    alert("No standalone 'subhead' phrase found in the selected text frame.");
                }
            }
        } else {
            alert("Please select a text frame or place the cursor inside a text frame.");
        }
    } else {
        alert("No active document found.");
    }
}

// Helper function to map capitalization constants to InDesign values
function getCapitalization(constantValue) {
    switch (constantValue) {
        case 1634493296:
            return Capitalization.ALL_CAPS;
        case 1664250723:
            return Capitalization.CAP_TO_SMALL_CAP;
        case 1852797549:
            return Capitalization.NORMAL;
        case 1936548720:
            return Capitalization.SMALL_CAPS;
        case 1919251315:
            return true; // For ruleAbove
        case 1919251316:
            return true; // For ruleBelow
        default:
            return Capitalization.NORMAL; // Default to normal capitalization
    }
}

// Run the function
findAndApplyTextSettings();

Votes

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