Copy link to clipboard
Copied
I have made a script which a user can design a range of consecutive subheaders and the script will apply the styles for all instances of subheaders
see screenshots for example
As you can see there are 4 subheaders each with text settiings and then other entries with similar subheaders - rather than having to eyedrop all of them you can run the script and all subheaders will be styles - see the second screenshot
As you can see each subhead has adopted the respective subhead.
The problem I have is if each subheader has a return after it the script does not see them as consecutive.
Screenshot below shows the issue
The same subheads but now with returns
as you can see once the script has been run they all adopt the frust subheader
Any advice on this would be most appreciated!
This should be a useful script when complete and it feels like it is the final hurdle.
Many thanks
Smyth
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 foundTargetParagraph = false;
var targetTextSettingsList = [];
// Iterate over each selected text frame
for (var j = 0; j < selectedTextFrames.length; j++) {
var paragraphs = selectedTextFrames[j].parentStory.paragraphs.everyItem().getElements();
// Find the first suitable paragraph and all consecutive ones
for (var i = 0; i < paragraphs.length; i++) {
var consecutiveParagraphs = [];
var allConsecutiveSettings = [];
for (var k = i; k < paragraphs.length; k++) {
var para = paragraphs[k];
var words = para.words.length;
var paragraphText = para.contents;
// Check criteria: 1 to 10 words and no full stop
if (words > 0 && words <= 10 && paragraphText.indexOf('.') === -1) {
consecutiveParagraphs.push(para);
allConsecutiveSettings.push(getTextSettings(para));
} else {
break; // Stop checking if the paragraph doesn't meet criteria
}
}
if (consecutiveParagraphs.length > 0) {
targetTextSettingsList = allConsecutiveSettings;
foundTargetParagraph = true;
break; // Exit loop once found
}
}
if (foundTargetParagraph) {
// Apply text settings to similar paragraphs within an undoable action
app.doScript(function() {
var currentConsecutiveIndex = 0;
for (var i = 0; i < paragraphs.length; i++) {
var para = paragraphs[i];
var words = para.words.length;
var paragraphText = para.contents;
// Apply text settings if it's a similar paragraph
if (words > 0 && words <= 10 && paragraphText.indexOf('.') === -1) {
if (currentConsecutiveIndex < targetTextSettingsList.length) {
applyTextSettings(para, targetTextSettingsList[currentConsecutiveIndex]);
currentConsecutiveIndex++;
}
} else {
currentConsecutiveIndex = 0; // Reset if paragraph does not meet criteria
}
}
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Apply Text Settings");
} else {
alert("No suitable paragraphs 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.");
}
}
// Function to get text settings from a paragraph
function getTextSettings(paragraph) {
return {
appliedFont: paragraph.appliedFont,
pointSize: paragraph.pointSize,
fillColor: paragraph.fillColor,
fillTint: paragraph.fillTint,
justification: paragraph.justification,
leading: paragraph.leading,
firstLineIndent: paragraph.firstLineIndent,
baselineShift: paragraph.baselineShift,
tracking: paragraph.tracking,
capitalization: getCapitalization(paragraph.capitalization),
alignToBaseline: paragraph.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
};
}
// Function to apply text settings to a paragraph
function applyTextSettings(paragraph, settings) {
paragraph.appliedFont = settings.appliedFont;
paragraph.pointSize = settings.pointSize;
paragraph.fillColor = settings.fillColor;
paragraph.fillTint = settings.fillTint;
paragraph.leading = settings.leading;
paragraph.firstLineIndent = settings.firstLineIndent;
paragraph.justification = settings.justification;
paragraph.ruleAbove = settings.ruleAbove;
paragraph.ruleAboveColor = settings.ruleAboveColor;
paragraph.ruleAboveGapColor = settings.ruleAboveGapColor;
paragraph.ruleAboveGapOverprint = settings.ruleAboveGapOverprint;
paragraph.ruleAboveGapTint = settings.ruleAboveGapTint;
paragraph.ruleAboveLeftIndent = settings.ruleAboveLeftIndent;
paragraph.ruleAboveLineWeight = settings.ruleAboveLineWeight;
paragraph.ruleAboveOffset = settings.ruleAboveOffset;
paragraph.ruleAboveOverprint = settings.ruleAboveOverprint;
paragraph.ruleAboveRightIndent = settings.ruleAboveRightIndent;
paragraph.ruleAboveTint = settings.ruleAboveTint;
paragraph.ruleAboveType = settings.ruleAboveType;
paragraph.ruleAboveWidth = settings.ruleAboveWidth;
paragraph.ruleBelow = settings.ruleBelow;
paragraph.ruleBelowColor = settings.ruleBelowColor;
paragraph.ruleBelowGapColor = settings.ruleBelowGapColor;
paragraph.ruleBelowGapOverprint = settings.ruleBelowGapOverprint;
paragraph.ruleBelowGapTint = settings.ruleBelowGapTint;
paragraph.ruleBelowLeftIndent = settings.ruleBelowLeftIndent;
paragraph.ruleBelowLineWeight = settings.ruleBelowLineWeight;
paragraph.ruleBelowOffset = settings.ruleBelowOffset;
paragraph.ruleBelowOverprint = settings.ruleBelowOverprint;
paragraph.ruleBelowRightIndent = settings.ruleBelowRightIndent;
paragraph.ruleBelowTint = settings.ruleBelowTint;
paragraph.ruleBelowType = settings.ruleBelowType;
paragraph.ruleBelowWidth = settings.ruleBelowWidth;
// Apply word-level settings to each word in the paragraph
var paraWords = paragraph.words.everyItem().getElements();
for (var k = 0; k < paraWords.length; k++) {
paraWords[k].appliedFont = settings.appliedFont;
paraWords[k].pointSize = settings.pointSize;
paraWords[k].fillColor = settings.fillColor;
paraWords[k].fillTint = settings.fillTint;
paraWords[k].leading = settings.leading;
paraWords[k].baselineShift = settings.baselineShift;
paraWords[k].tracking = settings.tracking;
paraWords[k].capitalization = settings.capitalization;
paraWords[k].alignToBaseline = settings.alignToBaseline;
// Apply other text attributes as needed
}
}
// 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();
1 Correct answer
...I have made a script which a user can design a range of consecutive subheaders and the script will apply the styles for all instances of subheaders
see screenshots for example
As you can see there are 4 subheaders each with text settiings and then other entries with similar subheaders - rather than having to eyedrop all of them you can run the script and all subheaders will be styles - see the second screenshot
As you can see each subhead has adopted the respective subhead.
The problem I ha
Copy link to clipboard
Copied
I have made a script which a user can design a range of consecutive subheaders and the script will apply the styles for all instances of subheaders
see screenshots for example
As you can see there are 4 subheaders each with text settiings and then other entries with similar subheaders - rather than having to eyedrop all of them you can run the script and all subheaders will be styles - see the second screenshot
As you can see each subhead has adopted the respective subhead.
The problem I have is if each subheader has a return after it the script does not see them as consecutive.
Screenshot below shows the issueThe same subheads but now with returns
as you can see once the script has been run they all adopt the frust subheader
Any advice on this would be most appreciated!
This should be a useful script when complete and it feels like it is the final hurdle.
Many thanks
Smyth
Hello, @SmythWharfADPWorkforceNow
It’s great to see you working on this script to streamline subheader styling. Let’s tackle that final hurdle together!
From your description and the screenshots, it seems like you’ve made significant progress. However, handling consecutive subheaders with returns can indeed be tricky. I’ll provide some guidance to address this issue.
Identifying Consecutive Subheaders:
You’ve already defined the criteria for identifying subheaders: at least two hard enter returns (paragraph breaks), followed by a short string (up to 6 words) without a full stop.
The challenge lies in ensuring that these subheaders are recognized even when they have returns after them.
Script Enhancement:
To handle consecutive subheaders with returns, consider modifying your script as follows:
Instead of looking for a single instance of the word “test” (as in your initial working script), look for the subheader pattern.
Use regular expressions (regex) to match the specific criteria for subheaders.
Iterate through the paragraphs and apply the desired text settings to each identified subheader.
Sample Approach:
Here’s a high-level idea of how your script could be enhanced:
Define a regex pattern that matches your subheader criteria (e.g., two or more hard returns followed by a short string without a full stop).
Loop through the paragraphs in the text frame.
For each paragraph, check if it matches the subheader pattern.
If it does, apply the desired text settings to that paragraph.
Example (Pseudo-Code):
// Define your regex pattern for subheaders
var subheaderRegex = /(\r\n){2,}[^.]{1,6}$/;
// Loop through paragraphs
for (var i = 0; i < paragraphs.length; i++) {
var para = paragraphs[i];
if (subheaderRegex.test(para.contents)) {
// Apply text settings to identified subheader
// ...
}
}
Testing and Refining:
Test this enhanced script with various scenarios (including subheaders with returns) to ensure it correctly identifies and styles them.
Adjust the regex pattern or other conditions as needed based on real-world examples.
Remember, scripting is like solving a puzzle—sometimes it takes a few iterations to get it just right.
I hope this info is helpful to you.
Best Regard,
Gregory Chavez
Copy link to clipboard
Copied
Hello,
managed to get a fix quite some time ago
try this
// Main function to find and apply text settings to consecutive paragraphs
function findAndApplyTextSettings() {
// Check if 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 foundTargetParagraph = false;
var targetTextSettingsList = [];
// Iterate over each selected text frame
for (var j = 0; j < selectedTextFrames.length; j++) {
var textFrame = selectedTextFrames[j];
var paragraphs = textFrame.parentStory.paragraphs.everyItem().getElements();
var consecutiveCount = 0;
var consecutiveParagraphs = [];
var allConsecutiveSettings = [];
// Loop through each paragraph
for (var i = 0; i < paragraphs.length; i++) {
var paragraph = paragraphs[i];
// Check if the paragraph is empty
if (paragraph.contents.replace(/^\s+|\s+$/g, '').length === 0) {
continue; // Skip empty paragraphs without resetting the count
}
// Check if the paragraph meets the criteria
if (isValidParagraph(paragraph)) {
consecutiveCount++;
consecutiveParagraphs.push(paragraph);
allConsecutiveSettings.push(getTextSettings(paragraph));
} else {
// If consecutiveCount is greater than 0, process the consecutive paragraphs found
if (consecutiveCount > 0) {
if (!foundTargetParagraph) {
targetTextSettingsList = allConsecutiveSettings;
foundTargetParagraph = true;
}
applyTextSettingsToConsecutive(consecutiveParagraphs, targetTextSettingsList);
consecutiveCount = 0; // Reset consecutive count
consecutiveParagraphs = [];
allConsecutiveSettings = [];
} else {
consecutiveCount = 0; // Reset consecutive count
consecutiveParagraphs = [];
allConsecutiveSettings = [];
}
}
}
// After the loop, apply settings if found
if (foundTargetParagraph) {
break; // Exit loop over selected text frames once settings applied
} else {
alert("No subheaders found with corresponding paragraphs. \nPlease use the list script instead.");
}
}
} else {
alert("Please select a text frame or place the cursor inside a text frame.");
}
} else {
alert("No active document found.");
}
}
// Function to check if a paragraph meets the criteria
function isValidParagraph(paragraph) {
// Ignore empty paragraphs (no characters)
if (paragraph.contents.replace(/^\s+|\s+$/g, '').length === 0) {
return false;
}
// Split the paragraph into words
var words = paragraph.words;
// Check number of words and absence of period
if (words.length > 0 && words.length <= 10) {
// Access the last word in the collection
var lastWord = words.lastItem();
// Check if last word ends with a period
if (lastWord.contents.charAt(lastWord.contents.length - 1) === ".") {
return false;
}
// All conditions met
return true;
}
return false;
}
// Function to get text settings from a paragraph
function getTextSettings(paragraph) {
return {
appliedFont: paragraph.appliedFont,
pointSize: paragraph.pointSize,
fillColor: paragraph.fillColor,
fillTint: paragraph.fillTint,
justification: paragraph.justification,
leading: paragraph.leading,
firstLineIndent: paragraph.firstLineIndent,
baselineShift: paragraph.baselineShift,
tracking: paragraph.tracking,
capitalization: getCapitalization(paragraph.capitalization),
alignToBaseline: paragraph.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,
spaceBefore: paragraph.spaceBefore, // Add spaceBefore attribute
spaceAfter: paragraph.spaceAfter // Add spaceAfter attribute
// Add more text attributes as needed
};
}
// Function to apply text settings to a paragraph
function applyTextSettings(paragraph, settings) {
paragraph.appliedFont = settings.appliedFont;
paragraph.pointSize = settings.pointSize;
paragraph.fillColor = settings.fillColor;
paragraph.fillTint = settings.fillTint;
paragraph.leading = settings.leading;
paragraph.firstLineIndent = settings.firstLineIndent;
paragraph.justification = settings.justification;
paragraph.ruleAbove = settings.ruleAbove;
paragraph.ruleAboveColor = settings.ruleAboveColor;
paragraph.ruleAboveGapColor = settings.ruleAboveGapColor;
paragraph.ruleAboveGapOverprint = settings.ruleAboveGapOverprint;
paragraph.ruleAboveGapTint = settings.ruleAboveGapTint;
paragraph.ruleAboveLeftIndent = settings.ruleAboveLeftIndent;
paragraph.ruleAboveLineWeight = settings.ruleAboveLineWeight;
paragraph.ruleAboveOffset = settings.ruleAboveOffset;
paragraph.ruleAboveOverprint = settings.ruleAboveOverprint;
paragraph.ruleAboveRightIndent = settings.ruleAboveRightIndent;
paragraph.ruleAboveTint = settings.ruleAboveTint;
paragraph.ruleAboveType = settings.ruleAboveType;
paragraph.ruleAboveWidth = settings.ruleAboveWidth;
paragraph.ruleBelow = settings.ruleBelow;
paragraph.ruleBelowColor = settings.ruleBelowColor;
paragraph.ruleBelowGapColor = settings.ruleBelowGapColor;
paragraph.ruleBelowGapOverprint = settings.ruleBelowGapOverprint;
paragraph.ruleBelowGapTint = settings.ruleBelowGapTint;
paragraph.ruleBelowLeftIndent = settings.ruleBelowLeftIndent;
paragraph.ruleBelowLineWeight = settings.ruleBelowLineWeight;
paragraph.ruleBelowOffset = settings.ruleBelowOffset;
paragraph.ruleBelowOverprint = settings.ruleBelowOverprint;
paragraph.ruleBelowRightIndent = settings.ruleBelowRightIndent;
paragraph.ruleBelowTint = settings.ruleBelowTint;
paragraph.ruleBelowType = settings.ruleBelowType;
paragraph.ruleBelowWidth = settings.ruleBelowWidth;
paragraph.spaceBefore = settings.spaceBefore; // Apply spaceBefore
paragraph.spaceAfter = settings.spaceAfter; // Apply spaceAfter
// Apply word-level settings to each word in the paragraph
var paraWords = paragraph.words.everyItem().getElements();
for (var k = 0; k < paraWords.length; k++) {
paraWords[k].appliedFont = settings.appliedFont;
paraWords[k].pointSize = settings.pointSize;
paraWords[k].fillColor = settings.fillColor;
paraWords[k].fillTint = settings.fillTint;
paraWords[k].leading = settings.leading;
paraWords[k].baselineShift = settings.baselineShift;
paraWords[k].tracking = settings.tracking;
paraWords[k].capitalization = settings.capitalization;
paraWords[k].alignToBaseline = settings.alignToBaseline;
// Apply other text attributes as needed
}
}
// Function to apply text settings to consecutive paragraphs
function applyTextSettingsToConsecutive(paragraphs, settingsList) {
app.doScript(function() {
var currentConsecutiveIndex = 0;
for (var i = 0; i < paragraphs.length; i++) {
var para = paragraphs[i];
var words = para.words.length;
var paragraphText = para.contents;
// Apply text settings if it's a similar paragraph
if (words > 0 && words <= 10 && paragraphText.indexOf('.') === -1) {
if (currentConsecutiveIndex < settingsList.length) {
applyTextSettings(para, settingsList[currentConsecutiveIndex]);
currentConsecutiveIndex++;
}
} else {
currentConsecutiveIndex = 0; // Reset if paragraph does not meet criteria
}
}
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Apply Text Settings");
}
// 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 to find and apply text settings
app.doScript(function() {
findAndApplyTextSettings();
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Find and Apply Text Settings");
Copy link to clipboard
Copied
You don't need this part of the code:
// Apply word-level settings to each word in the paragraph
var paraWords = paragraph.words.everyItem().getElements();
for (var k = 0; k < paraWords.length; k++) {
...
};
You can just apply your settings to the whole Paragraph - otherwise you'll end up with a lot of TextStyleRanges and spaces with possibly undetermined formatting.
And it will work faster.
Copy link to clipboard
Copied
Hello,
Ace, I should look into that,
thanks
Smyth
Copy link to clipboard
Copied
Hello,
I had a look at the suggestion.
Additionally, I have now added a feature to be able to automatically remove any paragraph indents in the frist non empty paragraph after consecutive and / or no consective subheader paragraphs.
Might be useful
// Main function to find and apply text settings to consecutive paragraphs
function findAndApplyTextSettings() {
// Check if 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 foundTargetParagraph = false;
var targetTextSettingsList = [];
var applyIndentAdjustment = false;
// Iterate over each selected text frame
for (var j = 0; j < selectedTextFrames.length; j++) {
var textFrame = selectedTextFrames[j];
var paragraphs = textFrame.parentStory.paragraphs.everyItem().getElements();
var consecutiveCount = 0;
var consecutiveParagraphs = [];
var allConsecutiveSettings = [];
var lastValidParagraph = null;
// Loop through each paragraph
for (var i = 0; i < paragraphs.length; i++) {
var paragraph = paragraphs[i];
// Check if the paragraph is empty
if (paragraph.contents.replace(/^\s+|\s+$/g, '').length === 0) {
continue; // Skip empty paragraphs without resetting the count
}
// Check if the paragraph meets the criteria for subheaders
if (isValidParagraph(paragraph)) {
consecutiveCount++;
consecutiveParagraphs.push(paragraph);
allConsecutiveSettings.push(getTextSettings(paragraph));
lastValidParagraph = paragraph; // Track the last valid paragraph
// Set flag to adjust indent for the next non-empty paragraph
applyIndentAdjustment = true;
} else {
// If consecutiveCount is greater than 0, process the consecutive paragraphs found
if (consecutiveCount > 0) {
if (!foundTargetParagraph) {
targetTextSettingsList = allConsecutiveSettings;
foundTargetParagraph = true;
}
applyTextSettingsToConsecutive(consecutiveParagraphs, targetTextSettingsList);
consecutiveCount = 0; // Reset consecutive count
consecutiveParagraphs = [];
allConsecutiveSettings = [];
lastValidParagraph = null;
applyIndentAdjustment = false;
} else {
consecutiveCount = 0; // Reset consecutive count
consecutiveParagraphs = [];
allConsecutiveSettings = [];
lastValidParagraph = null;
applyIndentAdjustment = false;
}
}
// If flag is set, adjust the indent of the next non-empty paragraph
if (applyIndentAdjustment) {
// Find the next non-empty paragraph
for (var k = i + 1; k < paragraphs.length; k++) {
var nextParagraph = paragraphs[k];
if (nextParagraph.contents.replace(/^\s+|\s+$/g, '').length > 0) {
nextParagraph.firstLineIndent = 0;
applyIndentAdjustment = false; // Reset flag after adjustment
break; // Stop checking after adjustment
}
}
}
}
// After the loop, apply settings if found
if (foundTargetParagraph) {
break; // Exit loop over selected text frames once settings applied
} else {
// Optionally, you can include a comment here to indicate no subheaders were found
// e.g., "No subheaders found with corresponding paragraphs."
}
}
} else {
// No valid selection or text frame found
}
} else {
// No active document found
}
}
// Function to check if a paragraph meets the criteria
function isValidParagraph(paragraph) {
// Ignore empty paragraphs (no characters)
if (paragraph.contents.replace(/^\s+|\s+$/g, '').length === 0) {
return false;
}
// Split the paragraph into words
var words = paragraph.words;
// Check number of words and absence of period
if (words.length > 0 && words.length <= 10) {
// Access the last word in the collection
var lastWord = words.lastItem();
// Check if last word ends with a period
if (lastWord.contents.charAt(lastWord.contents.length - 1) === ".") {
return false;
}
// All conditions met
return true;
}
return false;
}
// Function to get text settings from a paragraph
function getTextSettings(paragraph) {
return {
appliedFont: paragraph.appliedFont,
pointSize: paragraph.pointSize,
fillColor: paragraph.fillColor,
fillTint: paragraph.fillTint,
justification: paragraph.justification,
leading: paragraph.leading,
firstLineIndent: paragraph.firstLineIndent,
baselineShift: paragraph.baselineShift,
tracking: paragraph.tracking,
capitalization: getCapitalization(paragraph.capitalization),
alignToBaseline: paragraph.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,
spaceBefore: paragraph.spaceBefore, // Add spaceBefore attribute
spaceAfter: paragraph.spaceAfter // Add spaceAfter attribute
// Add more text attributes as needed
};
}
// Function to apply text settings to a paragraph
function applyTextSettings(paragraph, settings) {
paragraph.appliedFont = settings.appliedFont;
paragraph.pointSize = settings.pointSize;
paragraph.fillColor = settings.fillColor;
paragraph.fillTint = settings.fillTint;
paragraph.leading = settings.leading;
paragraph.firstLineIndent = settings.firstLineIndent;
paragraph.justification = settings.justification;
paragraph.ruleAbove = settings.ruleAbove;
paragraph.ruleAboveColor = settings.ruleAboveColor;
paragraph.ruleAboveGapColor = settings.ruleAboveGapColor;
paragraph.ruleAboveGapOverprint = settings.ruleAboveGapOverprint;
paragraph.ruleAboveGapTint = settings.ruleAboveGapTint;
paragraph.ruleAboveLeftIndent = settings.ruleAboveLeftIndent;
paragraph.ruleAboveLineWeight = settings.ruleAboveLineWeight;
paragraph.ruleAboveOffset = settings.ruleAboveOffset;
paragraph.ruleAboveOverprint = settings.ruleAboveOverprint;
paragraph.ruleAboveRightIndent = settings.ruleAboveRightIndent;
paragraph.ruleAboveTint = settings.ruleAboveTint;
paragraph.ruleAboveType = settings.ruleAboveType;
paragraph.ruleAboveWidth = settings.ruleAboveWidth;
paragraph.ruleBelow = settings.ruleBelow;
paragraph.ruleBelowColor = settings.ruleBelowColor;
paragraph.ruleBelowGapColor = settings.ruleBelowGapColor;
paragraph.ruleBelowGapOverprint = settings.ruleBelowGapOverprint;
paragraph.ruleBelowGapTint = settings.ruleBelowGapTint;
paragraph.ruleBelowLeftIndent = settings.ruleBelowLeftIndent;
paragraph.ruleBelowLineWeight = settings.ruleBelowLineWeight;
paragraph.ruleBelowOffset = settings.ruleBelowOffset;
paragraph.ruleBelowOverprint = settings.ruleBelowOverprint;
paragraph.ruleBelowRightIndent = settings.ruleBelowRightIndent;
paragraph.ruleBelowTint = settings.ruleBelowTint;
paragraph.ruleBelowType = settings.ruleBelowType;
paragraph.ruleBelowWidth = settings.ruleBelowWidth;
paragraph.spaceBefore = settings.spaceBefore; // Apply spaceBefore
paragraph.spaceAfter = settings.spaceAfter; // Apply spaceAfter
}
// Function to apply text settings to consecutive paragraphs
function applyTextSettingsToConsecutive(paragraphs, settingsList) {
app.doScript(function() {
var currentConsecutiveIndex = 0;
for (var i = 0; i < paragraphs.length; i++) {
var para = paragraphs[i];
var words = para.words.length;
var paragraphText = para.contents;
// Apply text settings if it's a similar paragraph
if (words > 0 && words <= 10 && paragraphText.indexOf('.') === -1) {
if (currentConsecutiveIndex < settingsList.length) {
applyTextSettings(para, settingsList[currentConsecutiveIndex]);
currentConsecutiveIndex++;
}
} else {
currentConsecutiveIndex = 0; // Reset if paragraph does not meet criteria
}
}
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Apply Text Settings");
}
// 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 to find and apply text settings
app.doScript(function() {
findAndApplyTextSettings();
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Find and Apply Text Settings");
Copy link to clipboard
Copied
Another adjustment
A user can now have a range of text boxes selected and the script will run over them left to right.
This gives users two ways to begin - cursor in the frame, or selection of one or now more text frames.
I will probs add a feature for a control regarding tick box for indent on the pargraph being indented to zero - but that is tbc
// Main function to find and apply text settings to consecutive paragraphs
function findAndApplyTextSettings() {
// Check if 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) {
var selectedTextFrames = [];
// Collect all text frames from selection
for (var i = 0; i < selection.length; i++) {
if (selection[i] instanceof TextFrame) {
selectedTextFrames.push(selection[i]);
} else if (selection[i].hasOwnProperty('insertionPoints')) {
selectedTextFrames.push(selection[i].parentTextFrames[0]);
}
}
if (selectedTextFrames.length === 0) {
alert("No valid text frames found in selection.");
return;
}
// Process each text frame individually
for (var j = 0; j < selectedTextFrames.length; j++) {
processTextFrame(selectedTextFrames[j]);
}
} else {
// No valid selection
alert("Please select at least one text frame or insertion point.");
}
} else {
// No active document found
alert("No active document found.");
}
}
// Function to process a single text frame
function processTextFrame(textFrame) {
var paragraphs = textFrame.parentStory.paragraphs.everyItem().getElements();
var foundTargetParagraph = false;
var targetTextSettingsList = [];
var applyIndentAdjustment = false;
var consecutiveCount = 0;
var consecutiveParagraphs = [];
var allConsecutiveSettings = [];
var lastValidParagraph = null;
// Loop through each paragraph
for (var i = 0; i < paragraphs.length; i++) {
var paragraph = paragraphs[i];
// Check if the paragraph is empty
if (paragraph.contents.replace(/^\s+|\s+$/g, '').length === 0) {
continue; // Skip empty paragraphs without resetting the count
}
// Check if the paragraph meets the criteria for subheaders
if (isValidParagraph(paragraph)) {
consecutiveCount++;
consecutiveParagraphs.push(paragraph);
allConsecutiveSettings.push(getTextSettings(paragraph));
lastValidParagraph = paragraph; // Track the last valid paragraph
// Set flag to adjust indent for the next non-empty paragraph
applyIndentAdjustment = true;
} else {
// If consecutiveCount is greater than 0, process the consecutive paragraphs found
if (consecutiveCount > 0) {
if (!foundTargetParagraph) {
targetTextSettingsList = allConsecutiveSettings;
foundTargetParagraph = true;
}
applyTextSettingsToConsecutive(consecutiveParagraphs, targetTextSettingsList);
consecutiveCount = 0; // Reset consecutive count
consecutiveParagraphs = [];
allConsecutiveSettings = [];
lastValidParagraph = null;
applyIndentAdjustment = false;
} else {
consecutiveCount = 0; // Reset consecutive count
consecutiveParagraphs = [];
allConsecutiveSettings = [];
lastValidParagraph = null;
applyIndentAdjustment = false;
}
}
// If flag is set, adjust the indent of the next non-empty paragraph
if (applyIndentAdjustment) {
// Find the next non-empty paragraph
for (var k = i + 1; k < paragraphs.length; k++) {
var nextParagraph = paragraphs[k];
if (nextParagraph.contents.replace(/^\s+|\s+$/g, '').length > 0) {
nextParagraph.firstLineIndent = 0;
applyIndentAdjustment = false; // Reset flag after adjustment
break; // Stop checking after adjustment
}
}
}
}
// After the loop, apply settings if found
if (foundTargetParagraph) {
// Optionally handle cases where settings were found
} else {
// Optionally handle cases where no subheaders were found
}
}
// Function to check if a paragraph meets the criteria
function isValidParagraph(paragraph) {
// Ignore empty paragraphs (no characters)
if (paragraph.contents.replace(/^\s+|\s+$/g, '').length === 0) {
return false;
}
// Split the paragraph into words
var words = paragraph.words;
// Check number of words and absence of period
if (words.length > 0 && words.length <= 10) {
// Access the last word in the collection
var lastWord = words.lastItem();
// Check if last word ends with a period
if (lastWord.contents.charAt(lastWord.contents.length - 1) === ".") {
return false;
}
// All conditions met
return true;
}
return false;
}
// Function to get text settings from a paragraph
function getTextSettings(paragraph) {
return {
appliedFont: paragraph.appliedFont,
pointSize: paragraph.pointSize,
fillColor: paragraph.fillColor,
fillTint: paragraph.fillTint,
justification: paragraph.justification,
leading: paragraph.leading,
firstLineIndent: paragraph.firstLineIndent,
baselineShift: paragraph.baselineShift,
tracking: paragraph.tracking,
capitalization: getCapitalization(paragraph.capitalization),
alignToBaseline: paragraph.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,
spaceBefore: paragraph.spaceBefore, // Add spaceBefore attribute
spaceAfter: paragraph.spaceAfter // Add spaceAfter attribute
// Add more text attributes as needed
};
}
// Function to apply text settings to a paragraph
function applyTextSettings(paragraph, settings) {
paragraph.appliedFont = settings.appliedFont;
paragraph.pointSize = settings.pointSize;
paragraph.fillColor = settings.fillColor;
paragraph.fillTint = settings.fillTint;
paragraph.leading = settings.leading;
paragraph.firstLineIndent = settings.firstLineIndent;
paragraph.justification = settings.justification;
paragraph.ruleAbove = settings.ruleAbove;
paragraph.ruleAboveColor = settings.ruleAboveColor;
paragraph.ruleAboveGapColor = settings.ruleAboveGapColor;
paragraph.ruleAboveGapOverprint = settings.ruleAboveGapOverprint;
paragraph.ruleAboveGapTint = settings.ruleAboveGapTint;
paragraph.ruleAboveLeftIndent = settings.ruleAboveLeftIndent;
paragraph.ruleAboveLineWeight = settings.ruleAboveLineWeight;
paragraph.ruleAboveOffset = settings.ruleAboveOffset;
paragraph.ruleAboveOverprint = settings.ruleAboveOverprint;
paragraph.ruleAboveRightIndent = settings.ruleAboveRightIndent;
paragraph.ruleAboveTint = settings.ruleAboveTint;
paragraph.ruleAboveType = settings.ruleAboveType;
paragraph.ruleAboveWidth = settings.ruleAboveWidth;
paragraph.ruleBelow = settings.ruleBelow;
paragraph.ruleBelowColor = settings.ruleBelowColor;
paragraph.ruleBelowGapColor = settings.ruleBelowGapColor;
paragraph.ruleBelowGapOverprint = settings.ruleBelowGapOverprint;
paragraph.ruleBelowGapTint = settings.ruleBelowGapTint;
paragraph.ruleBelowLeftIndent = settings.ruleBelowLeftIndent;
paragraph.ruleBelowLineWeight = settings.ruleBelowLineWeight;
paragraph.ruleBelowOffset = settings.ruleBelowOffset;
paragraph.ruleBelowOverprint = settings.ruleBelowOverprint;
paragraph.ruleBelowRightIndent = settings.ruleBelowRightIndent;
paragraph.ruleBelowTint = settings.ruleBelowTint;
paragraph.ruleBelowType = settings.ruleBelowType;
paragraph.ruleBelowWidth = settings.ruleBelowWidth;
paragraph.spaceBefore = settings.spaceBefore; // Apply spaceBefore
paragraph.spaceAfter = settings.spaceAfter; // Apply spaceAfter
}
// Function to apply text settings to consecutive paragraphs
function applyTextSettingsToConsecutive(paragraphs, settingsList) {
app.doScript(function() {
var currentConsecutiveIndex = 0;
for (var i = 0; i < paragraphs.length; i++) {
var para = paragraphs[i];
var words = para.words.length;
var paragraphText = para.contents;
// Apply text settings if it's a similar paragraph
if (words > 0 && words <= 10 && paragraphText.indexOf('.') === -1) {
if (currentConsecutiveIndex < settingsList.length) {
applyTextSettings(para, settingsList[currentConsecutiveIndex]);
currentConsecutiveIndex++;
}
} else {
currentConsecutiveIndex = 0; // Reset if paragraph does not meet criteria
}
}
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Apply Text Settings");
}
// 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 to find and apply text settings
app.doScript(function() {
findAndApplyTextSettings();
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Find and Apply Text Settings");
Copy link to clipboard
Copied
New update - now carries caps and baseline rules across subheades
// Main function to find and apply text settings to consecutive paragraphs
function findAndApplyTextSettings() {
// Check if 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) {
var selectedTextFrames = [];
// Collect all text frames from selection
for (var i = 0; i < selection.length; i++) {
if (selection[i] instanceof TextFrame) {
selectedTextFrames.push(selection[i]);
} else if (selection[i].hasOwnProperty('insertionPoints')) {
selectedTextFrames.push(selection[i].parentTextFrames[0]);
}
}
if (selectedTextFrames.length === 0) {
alert("No valid text frames found in selection.");
return;
}
// Process each text frame individually
for (var j = 0; j < selectedTextFrames.length; j++) {
processTextFrame(selectedTextFrames[j]);
}
} else {
// No valid selection
alert("Please select at least one text frame or insertion point.");
}
} else {
// No active document found
alert("No active document found.");
}
}
// Function to process a single text frame
function processTextFrame(textFrame) {
var paragraphs = textFrame.parentStory.paragraphs.everyItem().getElements();
var foundTargetParagraph = false;
var targetTextSettingsList = [];
var applyIndentAdjustment = false;
var consecutiveCount = 0;
var consecutiveParagraphs = [];
var allConsecutiveSettings = [];
var lastValidParagraph = null;
// Loop through each paragraph
for (var i = 0; i < paragraphs.length; i++) {
var paragraph = paragraphs[i];
// Check if the paragraph is empty
if (paragraph.contents.replace(/^\s+|\s+$/g, '').length === 0) {
continue; // Skip empty paragraphs without resetting the count
}
// Check if the paragraph meets the criteria for subheaders
if (isValidParagraph(paragraph)) {
consecutiveCount++;
consecutiveParagraphs.push(paragraph);
allConsecutiveSettings.push(getTextSettings(paragraph));
lastValidParagraph = paragraph; // Track the last valid paragraph
// Set flag to adjust indent for the next non-empty paragraph
applyIndentAdjustment = true;
} else {
// If consecutiveCount is greater than 0, process the consecutive paragraphs found
if (consecutiveCount > 0) {
if (!foundTargetParagraph) {
targetTextSettingsList = allConsecutiveSettings;
foundTargetParagraph = true;
}
applyTextSettingsToConsecutive(consecutiveParagraphs, targetTextSettingsList);
consecutiveCount = 0; // Reset consecutive count
consecutiveParagraphs = [];
allConsecutiveSettings = [];
lastValidParagraph = null;
applyIndentAdjustment = false;
} else {
consecutiveCount = 0; // Reset consecutive count
consecutiveParagraphs = [];
allConsecutiveSettings = [];
lastValidParagraph = null;
applyIndentAdjustment = false;
}
}
// If flag is set, adjust the indent of the next non-empty paragraph
if (applyIndentAdjustment) {
// Find the next non-empty paragraph
for (var k = i + 1; k < paragraphs.length; k++) {
var nextParagraph = paragraphs[k];
if (nextParagraph.contents.replace(/^\s+|\s+$/g, '').length > 0) {
nextParagraph.firstLineIndent = 0;
applyIndentAdjustment = false; // Reset flag after adjustment
break; // Stop checking after adjustment
}
}
}
}
// After the loop, apply settings if found
if (foundTargetParagraph) {
// Optionally handle cases where settings were found
} else {
// Optionally handle cases where no subheaders were found
}
}
// Function to check if a paragraph meets the criteria
function isValidParagraph(paragraph) {
// Ignore empty paragraphs (no characters)
if (paragraph.contents.replace(/^\s+|\s+$/g, '').length === 0) {
return false;
}
// Split the paragraph into words
var words = paragraph.words;
// Check number of words and absence of period
if (words.length > 0 && words.length <= 10) {
// Access the last word in the collection
var lastWord = words.lastItem();
// Check if last word ends with a period
if (lastWord.contents.charAt(lastWord.contents.length - 1) === ".") {
return false;
}
// All conditions met
return true;
}
return false;
}
// Function to get text settings from a paragraph
function getTextSettings(paragraph) {
return {
appliedFont: paragraph.appliedFont,
pointSize: paragraph.pointSize,
fillColor: paragraph.fillColor,
fillTint: paragraph.fillTint,
justification: paragraph.justification,
leading: paragraph.leading,
firstLineIndent: paragraph.firstLineIndent,
baselineShift: paragraph.baselineShift,
tracking: paragraph.tracking,
capitalization: getCapitalization(paragraph.capitalization),
alignToBaseline: paragraph.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,
spaceBefore: paragraph.spaceBefore, // Add spaceBefore attribute
spaceAfter: paragraph.spaceAfter // Add spaceAfter attribute
// Add more text attributes as needed
};
}
// Function to apply text settings to a paragraph
function applyTextSettings(paragraph, settings) {
paragraph.appliedFont = settings.appliedFont;
paragraph.pointSize = settings.pointSize;
paragraph.fillColor = settings.fillColor;
paragraph.fillTint = settings.fillTint;
paragraph.leading = settings.leading;
paragraph.firstLineIndent = settings.firstLineIndent;
paragraph.justification = settings.justification;
paragraph.baselineShift = settings.baselineShift; // Apply baselineShift
paragraph.tracking = settings.tracking; // Apply tracking
paragraph.capitalization = settings.capitalization; // Apply capitalization
paragraph.alignToBaseline = settings.alignToBaseline; // Apply alignToBaseline
paragraph.ruleAbove = settings.ruleAbove; // Apply ruleAbove
paragraph.ruleAboveColor = settings.ruleAboveColor; // Apply ruleAboveColor
paragraph.ruleAboveGapColor = settings.ruleAboveGapColor; // Apply ruleAboveGapColor
paragraph.ruleAboveGapOverprint = settings.ruleAboveGapOverprint; // Apply ruleAboveGapOverprint
paragraph.ruleAboveGapTint = settings.ruleAboveGapTint; // Apply ruleAboveGapTint
paragraph.ruleAboveLeftIndent = settings.ruleAboveLeftIndent; // Apply ruleAboveLeftIndent
paragraph.ruleAboveLineWeight = settings.ruleAboveLineWeight; // Apply ruleAboveLineWeight
paragraph.ruleAboveOffset = settings.ruleAboveOffset; // Apply ruleAboveOffset
paragraph.ruleAboveOverprint = settings.ruleAboveOverprint; // Apply ruleAboveOverprint
paragraph.ruleAboveRightIndent = settings.ruleAboveRightIndent; // Apply ruleAboveRightIndent
paragraph.ruleAboveTint = settings.ruleAboveTint; // Apply ruleAboveTint
paragraph.ruleAboveType = settings.ruleAboveType; // Apply ruleAboveType
paragraph.ruleAboveWidth = settings.ruleAboveWidth; // Apply ruleAboveWidth
paragraph.ruleBelow = settings.ruleBelow; // Apply ruleBelow
paragraph.ruleBelowColor = settings.ruleBelowColor; // Apply ruleBelowColor
paragraph.ruleBelowGapColor = settings.ruleBelowGapColor; // Apply ruleBelowGapColor
paragraph.ruleBelowGapOverprint = settings.ruleBelowGapOverprint; // Apply ruleBelowGapOverprint
paragraph.ruleBelowGapTint = settings.ruleBelowGapTint; // Apply ruleBelowGapTint
paragraph.ruleBelowLeftIndent = settings.ruleBelowLeftIndent; // Apply ruleBelowLeftIndent
paragraph.ruleBelowLineWeight = settings.ruleBelowLineWeight; // Apply ruleBelowLineWeight
paragraph.ruleBelowOffset = settings.ruleBelowOffset; // Apply ruleBelowOffset
paragraph.ruleBelowOverprint = settings.ruleBelowOverprint; // Apply ruleBelowOverprint
paragraph.ruleBelowRightIndent = settings.ruleBelowRightIndent; // Apply ruleBelowRightIndent
paragraph.ruleBelowTint = settings.ruleBelowTint; // Apply ruleBelowTint
paragraph.ruleBelowType = settings.ruleBelowType; // Apply ruleBelowType
paragraph.ruleBelowWidth = settings.ruleBelowWidth; // Apply ruleBelowWidth
paragraph.spaceBefore = settings.spaceBefore; // Apply spaceBefore
paragraph.spaceAfter = settings.spaceAfter; // Apply spaceAfter
}
// Function to apply text settings to consecutive paragraphs
function applyTextSettingsToConsecutive(paragraphs, settingsList) {
app.doScript(function() {
var currentConsecutiveIndex = 0;
for (var i = 0; i < paragraphs.length; i++) {
var para = paragraphs[i];
var words = para.words.length;
var paragraphText = para.contents;
// Apply text settings if it's a similar paragraph
if (words > 0 && words <= 10 && paragraphText.indexOf('.') === -1) {
if (currentConsecutiveIndex < settingsList.length) {
applyTextSettings(para, settingsList[currentConsecutiveIndex]);
currentConsecutiveIndex++;
}
} else {
currentConsecutiveIndex = 0; // Reset if paragraph does not meet criteria
}
}
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Apply Text Settings");
}
// 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 to find and apply text settings
app.doScript(function() {
findAndApplyTextSettings();
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Find and Apply Text Settings");
Copy link to clipboard
Copied
If your first paragraphs have some formatting applied - I assume through ParaStyles - why not just save the names of those ParaStyles and apply them when needed? Instead of saving and restoring some of the properties?
Copy link to clipboard
Copied
Hi Robert,
Below is an update version of the script which now takes into account if a user has a subheader styles via paragraph styles. It will now add that paragraph style throughout any automatically found headers. If the paragraph style has been adjusted by a user then it will use the users settings not the paragraph style.
However, I think this is missing the point.
The very purpose of this script is to provide an automated way of styling subheaders without the designer having to read through all the text. The designer can update the styles very easily through the first instance(s) subheaders.
Let me know if there are other pointer.
Thanks
Smyth
Notes on the below update
- Now takes note if a user has used a paaragaph style, will apply unedited paragraph styles to repective subheaders
- Now periods inside of subheaders less than words will not prevent styles from being applied, this allows for prices and numbered headers etc
// Main function to find and apply text settings to consecutive paragraphs
function findAndApplyTextSettings() {
if (app.documents.length > 0) {
var doc = app.activeDocument;
var selection = app.selection;
if (selection.length > 0) {
var selectedTextFrames = [];
for (var i = 0; i < selection.length; i++) {
if (selection[i] instanceof TextFrame) {
selectedTextFrames.push(selection[i]);
} else if (selection[i].hasOwnProperty('insertionPoints')) {
selectedTextFrames.push(selection[i].parentTextFrames[0]);
}
}
if (selectedTextFrames.length === 0) {
alert("No valid text frames found in selection.");
return;
}
for (var j = 0; j < selectedTextFrames.length; j++) {
processTextFrame(selectedTextFrames[j]);
}
} else {
alert("Please select at least one text frame or insertion point.");
}
} else {
alert("No active document found.");
}
}
// Function to process a single text frame
function processTextFrame(textFrame) {
var paragraphs = textFrame.parentStory.paragraphs.everyItem().getElements();
var foundTargetParagraph = false;
var targetTextSettingsList = [];
var applyIndentAdjustment = false;
var consecutiveCount = 0;
var consecutiveParagraphs = [];
var allConsecutiveSettings = [];
var lastValidParagraph = null;
for (var i = 0; i < paragraphs.length; i++) {
var paragraph = paragraphs[i];
if (paragraph.contents.replace(/^\s+|\s+$/g, '').length === 0) {
continue;
}
if (isValidParagraph(paragraph)) {
consecutiveCount++;
consecutiveParagraphs.push(paragraph);
allConsecutiveSettings.push(getTextSettings(paragraph));
lastValidParagraph = paragraph;
applyIndentAdjustment = true;
} else {
if (consecutiveCount > 0) {
if (!foundTargetParagraph) {
targetTextSettingsList = allConsecutiveSettings;
foundTargetParagraph = true;
}
applyTextSettingsToConsecutive(consecutiveParagraphs, targetTextSettingsList);
consecutiveCount = 0;
consecutiveParagraphs = [];
allConsecutiveSettings = [];
lastValidParagraph = null;
applyIndentAdjustment = false;
} else {
consecutiveCount = 0;
consecutiveParagraphs = [];
allConsecutiveSettings = [];
lastValidParagraph = null;
applyIndentAdjustment = false;
}
}
if (applyIndentAdjustment) {
for (var k = i + 1; k < paragraphs.length; k++) {
var nextParagraph = paragraphs[k];
if (nextParagraph.contents.replace(/^\s+|\s+$/g, '').length > 0) {
nextParagraph.firstLineIndent = 0;
applyIndentAdjustment = false;
break;
}
}
}
}
if (foundTargetParagraph) {
// Handle cases where settings were found
} else {
// Handle cases where no subheaders were found
}
}
// Function to check if a paragraph meets the criteria
function isValidParagraph(paragraph) {
var contents = paragraph.contents.replace(/^\s+|\s+$/g, '');
if (contents.length === 0) {
return false;
}
var words = paragraph.words;
if (words.length > 0 && words.length <= 10) {
var lastWord = words.lastItem();
var lastWordContents = lastWord.contents;
// Check if the last word ends with a period
if (lastWordContents.charAt(lastWordContents.length - 1) === ".") {
// Check if the period is part of a number or abbreviation
var periodPattern = /\d+\.\d+|[a-zA-Z]\.\s*$/;
if (periodPattern.test(lastWordContents)) {
return true;
} else {
return false;
}
}
return true;
}
return false;
}
// Function to get text settings from a paragraph
function getTextSettings(paragraph) {
var settings = {
appliedFont: paragraph.appliedFont,
pointSize: paragraph.pointSize,
fillColor: paragraph.fillColor,
fillTint: paragraph.fillTint,
justification: paragraph.justification,
leading: paragraph.leading,
firstLineIndent: paragraph.firstLineIndent,
baselineShift: paragraph.baselineShift,
tracking: paragraph.tracking,
capitalization: getCapitalization(paragraph.capitalization),
alignToBaseline: paragraph.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,
spaceBefore: paragraph.spaceBefore,
spaceAfter: paragraph.spaceAfter
};
var paragraphStyle = paragraph.appliedParagraphStyle;
if (paragraphStyle.isValid && isStyleUnmodified(paragraph, paragraphStyle)) {
settings.paragraphStyle = paragraphStyle;
} else {
settings.paragraphStyle = null;
}
return settings;
}
// Function to check if the paragraph matches its base paragraph style
function isStyleUnmodified(paragraph, paragraphStyle) {
var styleProperties = ['appliedFont', 'pointSize', 'fillColor', 'fillTint', 'justification', 'leading', 'firstLineIndent', 'baselineShift', 'tracking', 'capitalization', 'alignToBaseline', 'ruleAbove', 'ruleBelow', 'spaceBefore', 'spaceAfter'];
for (var i = 0; i < styleProperties.length; i++) {
var prop = styleProperties[i];
if (paragraph[prop] !== paragraphStyle[prop]) {
return false;
}
}
return true;
}
// Function to apply text settings to a paragraph
function applyTextSettings(paragraph, settings) {
if (settings.paragraphStyle) {
paragraph.applyParagraphStyle(settings.paragraphStyle, true);
} else {
paragraph.appliedFont = settings.appliedFont;
paragraph.pointSize = settings.pointSize;
paragraph.fillColor = settings.fillColor;
paragraph.fillTint = settings.fillTint;
paragraph.leading = settings.leading;
paragraph.firstLineIndent = settings.firstLineIndent;
paragraph.justification = settings.justification;
paragraph.baselineShift = settings.baselineShift;
paragraph.tracking = settings.tracking;
paragraph.capitalization = settings.capitalization;
paragraph.alignToBaseline = settings.alignToBaseline;
paragraph.ruleAbove = settings.ruleAbove;
paragraph.ruleAboveColor = settings.ruleAboveColor;
paragraph.ruleAboveGapColor = settings.ruleAboveGapColor;
paragraph.ruleAboveGapOverprint = settings.ruleAboveGapOverprint;
paragraph.ruleAboveGapTint = settings.ruleAboveGapTint;
paragraph.ruleAboveLeftIndent = settings.ruleAboveLeftIndent;
paragraph.ruleAboveLineWeight = settings.ruleAboveLineWeight;
paragraph.ruleAboveOffset = settings.ruleAboveOffset;
paragraph.ruleAboveOverprint = settings.ruleAboveOverprint;
paragraph.ruleAboveRightIndent = settings.ruleAboveRightIndent;
paragraph.ruleAboveTint = settings.ruleAboveTint;
paragraph.ruleAboveType = settings.ruleAboveType;
paragraph.ruleAboveWidth = settings.ruleAboveWidth;
paragraph.ruleBelow = settings.ruleBelow;
paragraph.ruleBelowColor = settings.ruleBelowColor;
paragraph.ruleBelowGapColor = settings.ruleBelowGapColor;
paragraph.ruleBelowGapOverprint = settings.ruleBelowGapOverprint;
paragraph.ruleBelowGapTint = settings.ruleBelowGapTint;
paragraph.ruleBelowLeftIndent = settings.ruleBelowLeftIndent;
paragraph.ruleBelowLineWeight = settings.ruleBelowLineWeight;
paragraph.ruleBelowOffset = settings.ruleBelowOffset;
paragraph.ruleBelowOverprint = settings.ruleBelowOverprint;
paragraph.ruleBelowRightIndent = settings.ruleBelowRightIndent;
paragraph.ruleBelowTint = settings.ruleBelowTint;
paragraph.ruleBelowType = settings.ruleBelowType;
paragraph.ruleBelowWidth = settings.ruleBelowWidth;
paragraph.spaceBefore = settings.spaceBefore;
paragraph.spaceAfter = settings.spaceAfter;
}
}
// Function to apply text settings to consecutive paragraphs
function applyTextSettingsToConsecutive(paragraphs, settingsList) {
app.doScript(function() {
var currentConsecutiveIndex = 0;
for (var i = 0; i < paragraphs.length; i++) {
var para = paragraphs[i];
var words = para.words.length;
var paragraphText = para.contents;
if (words > 0 && words <= 10 && !/^\d+(\.\d+)?$/.test(paragraphText)) {
if (currentConsecutiveIndex < settingsList.length) {
applyTextSettings(para, settingsList[currentConsecutiveIndex]);
currentConsecutiveIndex++;
}
} else {
currentConsecutiveIndex = 0;
}
}
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Apply Text Settings");
}
// 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;
case 1919251316:
return true;
default:
return Capitalization.NORMAL;
}
}
// Run the function to find and apply text settings
app.doScript(function() {
findAndApplyTextSettings();
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Find and Apply Text Settings");
Copy link to clipboard
Copied
I think you are missing my point - you should NEVER EVER use local formatting when working in InDesign.
So you should "promote" using Styles - ParaStyles in this case - which will also mean that your code will be much simpler AND faster.
If user will change formatting for those first few paragraphs - user will have to re-run your script.
But if ParaStyles are applied - your script needs to be run only once - unless user add more text.
Copy link to clipboard
Copied
Hello Robert,
Thank you for your feedback regarding the use of local formatting versus paragraph styles. I appreciate your insights and did implement the paragraph style aspect to the script.
However, I’d like to share some additional considerations:
In my experience, many designers in their roles use a combination of local formatting and paragraph styles.
I have also seen InDesign used with content mangement systems which mean paragaph styles can behave differently depending on the document people are working on. (This occurs when paragraph styles are preloaded with the document by default rather than empty documents which have styles assigned to them - don't ask me why I have seen this... mainly publishing houses. In short pullquote library item will look different based on document - although same library item and paragraph style.)
While creating a new paragraph style each time the script runs is an option, this could lead to a cluttered paragraph style list with multiple, perhaps unnecessary, styles—especially if designers change their preferences frequently based on client feedback or during the design process.
If the script was to change to do such, how would they be named so users can understand what the styles were. For example if each time it ran and it created another style, style 1, style 2, style n... this would get confusing.
Perhaps it creates the style once and then if changed it gets redefined? But how would it know when to make or redine a style? Any hints on this could be useful to think about.
Take into consideration that subheaders are stacked designers could test styles in a test bit of copy but people are lazy and so giving people a way to see subheader styles arross all text in the fastest way is my aim.
Regarding performance, I’ve tested the script with texts ranging from 3,000 to 5,000 words, and it performs the task in seconds—certainly faster than manual formatting. Additionally, the script allows for easy updates: a designer can modify the formatting of the first instance and run the script to apply those changes across the rest of the text in the set of threaded frames.
Having said that, yes they would need change the style for each frist instance header(s), and then to run the script for each parent frame. However, one would hope on such an expansive project, for example one would define the paragraph styles in the first header then run the script for all sets of frames and then if they needed to change something they can do it through the paragraph style menu. They could still use the script to style the copy though and it would be faster than by hand.
But on smaller projects layouts, poster updating header(s) even if you do have to do it for each parent threaded frame is still going to be faster than having to do it by hand.
I use this script regularly via a shortcut and find that speed wize it's negligible compared to redefining the paragraph style via the style menu. So for smaller projects like a big list entry etc it would be much the same, the main issue comes in the example above.
While the script might not be as elegant as a fully style-based approach, it provides practical benefits in environments where both local formatting and paragraph styles are used.
I don't mean to sound mistrusting of your advice, I simply wish to make the point that it's not entirely useless even if it is not following the best guidelines.
Again I would like to thank you again for your input—I’m always open to refining the tool further.
Best,
Smyth
Copy link to clipboard
Copied
One quick thought I had is - right now if you have the text box selected or the cursor in the text the scripts runs over all text. But this could behave differntly, i.e. text frame selection does all, but cursor in text would do everything beyond that point.
Might help issues where 10 headers and number 5, 7 both had subeaders. You could run the script again from that point as if you run it currently it would not work etc.
Anyhow it's all a work in progress
Copy link to clipboard
Copied
I'm not arguing that script is faster than doing it manually. That's why I've created my tool as well. And you've done a great job with your tool.
Even if you need / prefer to have local formatting - you can create a new / temporary ParaStyle, apply it to the texts - then delete and keep formatting.
There are 400+ Text properties - do you really want to rewrite all of them in the code?
Not sure what is wrong with CMS? You have a template that you populate with data - template dictates formatting - if it needs to be changed - styles can be redefined - for this particular situation - after template is populated.
If someone needs to create variations of the text to have multiple versions - it's still better to create copies of the styles, instead of local formatting - that can be lost with one wrong click...
If someone can't handle multiple sets of styles...
Copy link to clipboard
Copied
Hello,
Ah okay, so I can have tempory paragraph styles - okay I will dive into this....... didn't think of this as a tempory concept.
I understand your benifits regarding cutting down on lines of code avoiding the hard coding in of styles etc
Okay lemme take a look,
Best
Smyth
Copy link to clipboard
Copied
Scripting is to help people get job done quicker - but it doesn't mean, that coder needs to work harder.

