Copy link to clipboard
Copied
Hi
I'm trying to get the filColor for each paragraphStyle and characterStyle in a document. The (abbreviated) code below works just fine for paragraph styles.
for (mySCounter = 0; mySCounter < myDoc.paragraphStyles.length; mySCounter ++) {
var myPS = myDoc.paragraphStyles.item(mySCounter);
if (myPS.name != "[No Paragraph Style]" & myPS.name != "[Basic Paragraph]" & myPS.name != "PAGER") {
myTF.insertionPoints.item(-1).contents = "p." + myPS.name + " {\r"
+ "\tcolor: \"" + myPS.fillColor.name + "\";\r"
+ "}\r";
}
}
When I adapt it for character styles, though, Extendscript Toolkit burps at me.
for (mySCounter = 0; mySCounter < myDoc.characterStyles.length; mySCounter ++) {
var myCS = myDoc.characterStyles.item(mySCounter);
if (myCS.name != "[None]" & myCS.name != "pager") {
myTF.insertionPoints.item(-1).contents = "span." + myCS.name + " {\r"
+ "\tcolor: \"" + myCS.fillColor.name + "\";\r"
+ "}\r";
}
}
I've tried lots of variations with and without "name" in "myCSfillColor.name," including adding "toString()," "toSource()," and "toSpecifier()." The closest I can get to a valid return is "[object Color]." I'm not sure where the problem(s) lies, exactly. It could be that most of my character styles are returning a null, but that seems unlikely because I'm collecting other character style properties that are undefined, and they don't throw an error.
According to Jongware's help files, characterStyle.fillColor can return NothingEnum or a swatch while paragraphStyle.fillColor can only return a swatch. This seems to support the possiblity that those character styles that have no defined color are throwing the error, but I don't know what to do with that information. I could write an if statement, but the "\tcolor: ..." line above it in the middle of a long string that I'm building, and I can't think how I would put a conditional in the middle of that line.
Any thoughts on how I can capture the name of the fillColor for characterStyle? I can live with including "null" or "NOTHING" for those that are undefined.
I've pasted the full script below in case anyone wants to test it. It requires that a document be open and that it have at least one paragraph style other than "[Basic Paragraph]" and one character style other than "[None]." It will create a new document and dump into it selected properties of the paragraph and character styles (it's building a custom CSS template).
Thanks.
m.
CSS_Processor() // Invoke the framework for the processing routines
function CSS_Processor() {
app.textPreferences.typographersQuotes = false;
var myDoc = app.activeDocument;
var myStylesDoc = app.documents.add();
var myTF = myStylesDoc.pages.item(0).textFrames.add();
myTF.geometricBounds = [3, 3, 63, 48];
myTF.textFramePreferences.textColumnCount = 3;
for (mySCounter = 0; mySCounter < myDoc.paragraphStyles.length; mySCounter ++) {
var myPS = myDoc.paragraphStyles.item(mySCounter);
if (myPS.name != "[No Paragraph Style]" & myPS.name != "[Basic Paragraph]" & myPS.name != "PAGER") {
myTF.insertionPoints.item(-1).contents = "p." + myPS.name + " {\r"
+ "\tfont-family: \"" + myPS.appliedFont.name.slice(0, myPS.appliedFont.name.indexOf("\t")) + "\";\r"
+ "\tfont-style: \"" + myPS.fontStyle + "\";\r"
+ "\tfont-size: \"" + myPS.pointSize + "\";\r"
+ "\tline-height: \"" + myPS.leading + "\";\r"
+ "\tletter-spacing: \"" + myPS.kerningMethod + "\";\r"
+ "\tword-spacing: \"" + myPS.tracking + "\";\r"
+ "\tvertical-align: \"" + myPS.baselineShift + "\";\r"
+ "\ttext-align: \"" + myPS.justification.toString() + "\";\r"
+ "\tmargin-left: \"" + myPS.leftIndent + "\";\r"
+ "\tmargin-right: \"" + myPS.rightIndent + "\";\r"
+ "\ttext-indent: \"" + myPS.firstLineIndent + "\";\r"
+ "\tmargin-top: \"" + myPS.spaceBefore + "\";\r"
+ "\tmargin-bottom: \"" + myPS.spaceAfter + "\";\r"
+ "\torphans: \"" + myPS.keepFirstLines + "\";\r"
+ "\twidows: \"" + myPS.keepLastLines + "\";\r"
+ "\tkeep with next: \"" + myPS.keepWithNext + "\";\r"
+ "\tcolor: \"" + myPS.fillColor.name + "\";\r"
+ "\ttint: \"" + myPS.fillTint + "\";\r"
+ "\tcase: \"" + myPS.capitalization.toString() + "\";\r"
+ "\tposition: \"" + myPS.position.toString() + "\";\r"
+ "\tunderline: \"" + myPS.underline + "\";\r"
+ "\tstrikethrough: \"" + myPS.strikeThru + "\";\r"
+ "\thyphenation: \"" + myPS.hyphenation + "\";\r"
+ "}\r";
}
}
for (mySCounter = 0; mySCounter < myDoc.characterStyles.length; mySCounter ++) {
var myCS = myDoc.characterStyles.item(mySCounter);
if (myCS.name != "[None]" & myCS.name != "pager") {
myTF.insertionPoints.item(-1).contents = "span." + myCS.name + " {\r"
+ "\tfont-family: \"" + myCS.appliedFont.toString() + "\";\r"
+ "\tfont-style: \"" + myCS.fontStyle.toString() + "\";\r"
+ "\tfont-size: \"" + myCS.pointSize.toString() + "\";\r"
+ "\tline-height: \"" + myCS.leading.toString() + "\";\r"
+ "\tletter-spacing: \"" + myCS.kerningMethod.toString() + "\";\r"
+ "\tword-spacing: \"" + myCS.tracking.toString() + "\";\r"
+ "\tvertical-align: \"" + myCS.baselineShift.toString() + "\";\r"
+ "\tcolor: \"" + myCS.fillColor.toString() + "\";\r"
+ "\ttint: \"" + myCS.fillTint.toString() + "\";\r"
+ "\tcase: \"" + myCS.capitalization.toString() + "\";\r"
+ "\tposition: \"" + myCS.position.toString() + "\";\r"
+ "\tunderline: \"" + myCS.underline.toString() + "\";\r"
+ "\tstrikethrough: \"" + myCS.strikeThru.toString() + "\";\r"
+ "}\r";
}
}
/* myStylesDoc.exportFile(format:ExportFormat.TEXT_TYPE, to:folder.Desktop + "template.css");
myStylesDoc.close(); */
app.textPreferences.typographersQuotes = true;
}
Copy link to clipboard
Copied
Here's a way to put a conditional into the middle of that kind of statement:
myString = "Document has " + myStyles.length + " style" + (myStyles.length == 1 ? "" : "s") + ...
Dave
Copy link to clipboard
Copied
@Dave Saunders:
Thank you! Thank you! Thank you! With your help, I was able to write the conditional into the string, and it now works.
All the best.
m.
Copy link to clipboard
Copied
I've tried lots of variations with and without "name" in "myCSfillColor.name," including adding "toString()," "toSource()," and "toSpecifier()." The closest I can get to a valid return is "[object Color]."
That last one is only because it is specified as [object Color]. You say it works for paragraph styles. Now, what is the main difference between a character style and a paragraph style? You do not define everything in a character style.
Before you can ask for any property of the applied color (any property, in any way at all), you need to check if there is a color defined in it to begin with.
Copy link to clipboard
Copied
test for myCs.fillColor.isValid()
(use ternary operators for ease.)
Copy link to clipboard
Copied
Thanks for replying. I always find your comments helpful.
I follow what you're saying, but I don't understand why fillColor is different from any of the other properties I'm checking. For example, none of the character styles have a defined pointSize, either, but InDesign reports the pointSizve value of all of the character styles just fine.
Copy link to clipboard
Copied
when it comes to the Indesign DOM, asking "why" will give you a headache.
if the cstyles don't have defined a pointSize (or a leading, for that matter), they will return 1851876449 (meaning NothingEnum.NOTHING).
other properties, when not defined, will return null, and others will return various falsy values (for appliedFont, par example, will return empty string, that javascript will coerce to null). Why is that, and who though it's a good idea it's a different discussion.
just for reference, another weirdness, a paragraph style's appliedFont property will almost always return a Font object, but a cstyle will return a String (again, your mileage may vary, sometimes a pstyle will return a string, but i can't say when and why)
Copy link to clipboard
Copied
Vamitul wrote:
if the cstyles don't have defined a pointSize (or a leading, for that matter), they will return 1851876449 (meaning NothingEnum.NOTHING).
.. I was going to check if Linus was right on that, but of course you are correct -- this was my test script:
chs = app.activeDocument.characterStyles[1];
alert (chs.name);
alert (chs.fillColor);
// alert (chs.fillColor.name); // error!
alert ((chs.fillColor == null) ? 'Not set' : chs.fillColor.name);
alert (chs.pointSize); // ???
alert ( (chs.pointSize == NothingEnum.nothing) ? "Not set" : chs.pointSize);
but .. for the long list of properties in the original post, I would suggest an entirely different method -- easier to debug, easier to maintain and easier to understand. Instead of building one single long string (possibly interspersed with ternary operations), create an array and use push to add each of the property lines in turn:
cssprops = [];if (chs.fillColor != null)
cssprops.push('color: '+chs.fillColor.name+';');
Then use this
cssprops.join('\r')
to make it a single long line. It's easier to debug (etc.) because you typically need only one or two lines per inspected property. You can easily change the order in which properties are listed, and insert and remove any of the properties at will.
Copy link to clipboard
Copied
I would go even further, and make cssprops a object so I could initialize all the properties with null or something. as for listing all the properties, a simple "for x in this" will get the job done.
Later edit:
Here is something that might help you:
function main() {
var doc = app.activeDocument;
var cs = doc.characterStyles[2];
for (prop in cs) {
if ((cs[prop] != null) && (cs[prop] != NothingEnum.nothing)) {
if (cs[prop].hasOwnProperty('isValid') && cs[prop].isValid) {
$.writeln(prop + ' : ' + cs[prop].name)
} else {
$.writeln(prop + ' : ' + cs[prop])
}
} else {
$.writeln(prop + ' : null')
}
}
}
main()
Copy link to clipboard
Copied
Thanks, guys. As always, very insightful and helpful. Javascript and Extendscript are very new to me, so figuring out if I'm doing something wrong or if I'm running into an idiosyncracy can be a frustrating process, as I'm sure you all know.
I'm sure I'll be in touch again, but in the meantime, I need to pick up that book on Javascripting ID CS3 and 4. I read somewhere that a lot of it also applies to CS6.
Matthew