Copy link to clipboard
Copied
I do not think this is possible but as a book designer it would be very nice if there was a script. Is there a way to set my font style where my text is on one layer and my shading or rule (essentially a colour) is on a seperate layer? This is useful if the book needs a language change.
thanks
Dom
@m1b for a language change if the text is separate from any colored content it's possible to change the language by replacing only one plate (the one with the text). if the shading or rules are tied to the text you risk a shift in postion and then multiple plates must change.
You could duplicate the text frame to a new layer then give the copied text no fill and no stroke. Apply paragraph shading to the invisible text instead of the text on the language layer. Since the text is still there and matches whichever language you used as your source for copying the shading will match that language if you make any style (but not copy) changes.
Hi, Peter is correct, you do it as a 5 colour job, text as a spot black on its own layer. Printers print the CMYK and spot for one language, then replace the spot for the second language.
Copy link to clipboard
Copied
Is there a way to set my font style where my text is on one layer and my shading or rule (essentially a colour) is on a seperate layer?
No, Paragraph Rules and Paragraph Borders and Shading are paragraph attributes. If you wanted a rule or shading on a separate layer you would have to create the rules or shadows as separate objects.
Copy link to clipboard
Copied
Hi @DomRob Can you explain how it would be more useful than using the paragraph shading if the book needs a language change? Wouldn't it be better if, after changing the language, the shading just updated automatically to match the new text? Maybe you could post an example screen shot of what you mean?
- Mark
Copy link to clipboard
Copied
@m1b for a language change if the text is separate from any colored content it's possible to change the language by replacing only one plate (the one with the text). if the shading or rules are tied to the text you risk a shift in postion and then multiple plates must change.
Copy link to clipboard
Copied
Thanks @Peter Spier that could well be the salient factor.
Still, I have no idea what a hypothetical script would do.
Copy link to clipboard
Copied
Nor do I.
Copy link to clipboard
Copied
Maybe they can change the styles of the original text to no/paper color, which would preserve the shading/rules. Then have a new style for the new language that has no rules/shades.
Copy link to clipboard
Copied
Hi, Peter is correct, you do it as a 5 colour job, text as a spot black on its own layer. Printers print the CMYK and spot for one language, then replace the spot for the second language.
Copy link to clipboard
Copied
Seems like you would need to draw the rules/shading as separate shapes if you don't want them to change with text. Don't really see any other way around it.
Copy link to clipboard
Copied
You could duplicate the text frame to a new layer then give the copied text no fill and no stroke. Apply paragraph shading to the invisible text instead of the text on the language layer. Since the text is still there and matches whichever language you used as your source for copying the shading will match that language if you make any style (but not copy) changes.
Copy link to clipboard
Copied
Hi Scott
I have done this before, it is possible but it gets complicated, I do books with images, maps, graphs and at the moment I am on a 250 page book. The problem can be solved this way but for a second reprint the author has little changes which is where it gets complicated. Thanks, I thought it was unlikely but just needed to confirm it.
Copy link to clipboard
Copied
Sadly I think you are correct, thanks
Copy link to clipboard
Copied
Hi @DomRob, I wanted to write a script similar to what you are asking about, so here it is. Perhaps it could be helpful. All it does is search for specific paragraph-styled text and draw a box behind it. If you edit the text (eg. replace with translation) then re-run the script and it will update. Try out the attached demo.indd if you want to see it in action.
- Mark
/**
* @file Draw Boxes Around Styled Text.js
*
* Instructions:
* 1. Configure the `searchTerms` at the start of the script,
* so that script will search for text set in a particular
* paragraph style and draw a box around it.
*
* 2. Ensure that your document has the configured paragraph style
* and object style.
*
* 3. Run script.
*
* @author m1b
* @version 2025-09-02
* @discussion https://community.adobe.com/t5/indesign-discussions/style-sheets-to-split-text-and-shading-on-different-layers/m-p/15435479
*/
function main() {
/**
* searchTerm properties
* @property {String} paragraphStyleName - the paragraph style to search for.
* @property {String} objectStyleName - the object style to apply to the box.
* @property {String} label - *unique* label used to identify each box type.
* @property {String} layerName - the layer to draw boxes on.
* @property {Array<Number>} padding - the padding, in points, from each side of the text [T,L,B,R].
* @property {Boolean} oneBoxPerParagraph - if `true` draws one box per unbroken paragraph; if `false`, consectutive paragraphs will fit in the same box (default: false).
*/
var searchTerms = [
// demo search 1
{
paragraphStyleName: 'Breakout 1',
objectStyleName: 'Breakout 1',
label: 'box type 1',
layerName: 'Boxes',
padding: [2, 2, 2, 2],
oneBoxPerParagraph: true,
},
// demo search 2
{
paragraphStyleName: 'Breakout 2',
objectStyleName: 'Breakout 2',
label: 'box type 2',
layerName: 'Boxes',
padding: [10, 2, 10, 2],
oneBoxPerParagraph: true,
},
];
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
const isEmpty = /^[\s\r\n]*$/;
var doc = app.activeDocument;
var errors = [];
searchTermLoop:
for (var s = 0; s < searchTerms.length; s++) {
var searchTerm = searchTerms[s];
// collect the destination layer
var layer = getThing(doc.layers, 'name', searchTerm.layerName);
if (!layer) {
layer = doc.layers.add({ name: searchTerm.layerName });
layer.move(LocationOptions.AFTER, doc.layers.lastItem());
}
// collect the box object style
var objectStyle = getThing(doc.objectStyles, 'name', searchTerm.objectStyleName);
if (!objectStyle) {
errors.push('No object style "' + searchTerm.objectStyleName + '" found.');
continue searchTermLoop;
}
var paragraphStyle = getThing(doc.allParagraphStyles, 'name', searchTerm.paragraphStyleName);
if (!paragraphStyle) {
errors.push('No parragraph style "' + searchTerm.paragraphStyleName + '" found.');
continue searchTermLoop;
}
// collect the texts
var texts = findText(doc, { appliedParagraphStyle: paragraphStyle });
if (0 === texts.length) {
errors.push('No texts found for "' + searchTerm.paragraphStyleName + '" found.');
continue searchTermLoop;
}
if (searchTerm.oneBoxPerParagraph) {
// collect each paragraph from the texts
var paragraphs = [];
for (var i = 0; i < texts.length; i++)
paragraphs = paragraphs.concat(texts[i].paragraphs.everyItem().getElements());
texts = paragraphs;
}
// remove the previous boxes
var oldBoxes = doc.allPageItems;
for (var i = oldBoxes.length - 1; i >= 0; i--) {
if (searchTerm.label === oldBoxes[i].label)
oldBoxes[i].remove();
}
// draw the boxes
drawBoxesLoop:
for (var i = 0, bounds, box; i < texts.length; i++) {
if (isEmpty.test(texts[i].contents))
continue drawBoxesLoop;
bounds = getTextBounds(texts[i]);
bounds = [bounds[0] - searchTerm.padding[0], bounds[1] - searchTerm.padding[1], bounds[2] + searchTerm.padding[2], bounds[3] + searchTerm.padding[3]];
box = drawRectangleIndesign(doc, bounds, { label: searchTerm.label, appliedObjectStyle: objectStyle });
box.move(layer);
}
} // end search terms loop
if (errors.length)
alert('Errors:\n' + errors.join('\n'));
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Draw Boxes Around Styled Text');
/**
* Draws and returns a Rectangle.
* For Indesign
* @author m1b
* @version 2023-08-24
* @param {Document|Layer|Group} container - the container for the rectangle.
* @param {Array<Number>} bounds - rectangle bounds [T,L,B,R].
* @returns {Rectangle}
*/
function drawRectangleIndesign(container, bounds, props) {
var rectangle = container.rectangles.add({
geometricBounds: bounds,
});
if (props)
rectangle.properties = props;
return rectangle;
};
/**
* Returns the bounds of the text's metrics (not geometry).
* @author m1b
* @version 2025-09-02
* @param {Text} text
*/
function getTextBounds(text) {
if (
!text.hasOwnProperty('lines')
|| 0 === text.lines.length
)
throw new Error('getTextBounds: bad `lines` property.');
var top = Infinity;
var left = Infinity;
var bottom = -Infinity;
var right = -Infinity;
var tsrs = text.lines;
for (var i = 0, tsr, ltr, first, last; i < tsrs.length; i++) {
tsr = tsrs[i];
ltr = ParagraphDirectionOptions.LEFT_TO_RIGHT_DIRECTION === tsr.paragraphDirection;
first = tsr.characters.firstItem();
last = tsr.characters.lastItem();
if (ltr) {
if (first.horizontalOffset < left)
left = first.horizontalOffset;
if (last.endHorizontalOffset > right)
right = last.endHorizontalOffset;
}
else {
if (last.horizontalOffset < left)
left = last.horizontalOffset;
if (first.endHorizontalOffset > right)
right = first.endHorizontalOffset;
}
if (first.baseline - first.ascent < top)
top = first.baseline - first.ascent;
if (first.baseline + first.descent > bottom)
bottom = first.baseline + first.descent;
}
return [top, left, bottom, right];
};
/**
* Returns result of search in the supplied `findIn` object
* using its findText method.
*
* Example:
* var headingParas = findText(doc, { appliedParagraphStyle: headingStyle });
*
* @author m1b
* @version 2025-04-18
* @param {Document|Text} findIn - any object with a valid `findText` method.
* @param {Object} findWhat - an object containing findChangeTextOptions properties.
* @returns {Array<Text>}
*/
function findText(findIn, findWhat) {
if ('function' !== typeof findIn.findText)
throw new Error('findText: bad `where` supplied.');
// configure the find
app.findChangeTextOptions.properties = {
caseSensitive: false,
includeFootnotes: true,
includeHiddenLayers: false,
includeLockedLayersForFind: false,
includeLockedStoriesForFind: false,
includeMasterPages: false,
wholeWord: false,
};
// reset
app.findTextPreferences = NothingEnum.NOTHING;
for (var key in findWhat) {
if (
findWhat.hasOwnProperty(key)
&& app.findTextPreferences.hasOwnProperty(key)
)
app.findTextPreferences[key] = findWhat[key];
}
// perform the find
return findIn.findText();
};
/**
* Returns a thing with matching property.
* If `key` is undefined, evaluate the object itself.
* @author m1b
* @version 2024-04-21
* @param {Array|Collection} things - the things to look through.
* @param {String} [key] - the property name (default: undefined).
* @param {*} value - the value to match.
* @returns {*?} - the thing, if found.
*/
function getThing(things, key, value) {
for (var i = 0; i < things.length; i++)
if ((undefined == key ? things[i] : things[i][key]) == value)
return things[i];
};
Edit 2025-09-03: removed debugging line.
Copy link to clipboard
Copied
Hi @m1b Please view my PM in your inbox. Thank You
Find more inspiration, events, and resources on the new Adobe Community
Explore Now