JDX-сценарий inDesign добавляет заголовок и контент в textFrame
Я пытаюсь использовать сценарии inSesign JSX для вставки следующих данных в документ:
data = [{heading:"Heading 1", content: ["Some content"]},
{heading:"Heading 2", content: ["Some other content with", "Multiple paragraphs"]}]
Данные должны быть помещены в один TextFrame, но имеют разные стили для заголовка и содержимого.
Единственный способ, которым я могу видеть, чтобы добавить текст, это за один раз через textFrame.contents
переменная:
allContent = "";
headingParagraphs = []; // keep track of which paragraphs are headings
paragraph = 0;
for (var i = 0; i < data.length; i++) {
allContent += data.heading + "\r"; // Use a newline to split the paragraph
headingParagraphs.push(paragraph);
paragraph++;
for (var j = 0; j < data.content.length; j++) {
allContent += data.content[j] + "\r"; // Use a newline to split the paragraph
paragraph++;
}
}
textFrame.contents = allContent; // all data is in, but all text is styled the same
Затем, как только данные введены, я перебираю абзацы и добавляю стиль к заголовкам:
for (var i = 0; i < textFrame.paragraphs.count(); i++) {
if (headingParagraphs.indexOf(i) != -1) { // this is a heading paragraph
textFrame.paragraphs[i].pointSize = 20;
}
}
Это хорошо работает для небольших наборов данных, которые помещаются на одной странице, но как только содержимое становится больше, чем фрейм, paragraphs
возвращает только видимые абзацы. И если я перейду к новому textFrame, параграфы будут разбиты и headingParagraphs[]
массив больше не выстраивается.
В идеале я хотел бы добавить к содержимому и установить стили, прежде чем добавлять следующий контент - но в документации API не очень ясно, как вы можете это сделать (если вообще)
// Pseudo code:
for all sections:
append the heading to the frame, split to next page if needed
style all the *new* paragraphs as headings
for all section contents
append the content to the frame, split to next page if needed
style any *new* paragraphs as normal content
Есть ли способ добиться этого, используя функцию добавления или какой-либо другой способ назначить заголовки в нужном месте после добавления контента? Возможно, специальные символы в контенте для определения стиля?
1 ответ
Ваш длинный текст испорчен, потому что в настоящее время вы работаете внутри одного текстового фрейма. Как только текст уходит из этого одного фрейма, вы больше не можете называть его "принадлежащими" абзацам этого фрейма. использование parentStory
вместо этого, как он указывает на всю историю, внутри одного текстового фрейма или охватывающего более одного. Он также продолжает работать, если текст перезаписан.
Так что если у вас есть начальный кадр с именем textFrame
установите новую переменную story
в textFrame.parentStory
и используйте это, чтобы добавить текст.
Что касается добавления текста в этот фрейм (/story): действительно, нет быстрого способа добавить форматированный текст. настройка contents
работает только для длинных серий с одинаковым форматированием. Один из способов, который я использовал, - это записать текст в формате INX во временный файл и импортировать его. Это медленно для коротких фрагментов, но большие истории (до нескольких сотен страниц) могут быть очень эффективно созданы в самом Javascript, а затем импортировать их в ID... ну, это не так быстро, но быстрее, чем пытаться сделать это "вручную",
Другой способ - добавлять содержимое по одному абзацу за раз. Хитрость заключается в том, чтобы установить форматирование и добавить свой текст в story.insertionPoints[-1]
, Это, в особенно удобной записи, относится к самому последнему пункту вставки текста истории. Вы можете думать о точке вставки как о "текстовом курсоре"; Вы можете "применить" форматирование к нему, и любой добавленный текст будет иметь такое же форматирование.
Ваш фрагмент кода переработан, чтобы добавить один data
предмет за раз:
for (var i = 0; i < data.length; i++)
{
story.insertionPoints[-1].pointSize = 20;
story.insertionPoints[-1].contents = data[i].heading + "\r"; // Use a newline to split the paragraph
story.insertionPoints[-1].pointSize = 10;
for (var j = 0; j < data[i].content.length; j++)
{
story.insertionPoints[-1].contents = data[i].content[j] + "\r"; // Use a newline to split the paragraph
}
}
Стоит отметить, что вы не можете временно переопределить pointSize
Вот. Если вы установите больший размер, вы также должны снова установить исходный размер ("10" в моем фрагменте).
Могу ли я убедить вас использовать стили абзацев? Со стилями абзаца у вас будет что-то вроде
hdrStyle = app.activeDocument.paragraphStyles.item("Header");
textStyle = app.activeDocument.paragraphStyles.item("Text");
for (var i = 0; i < data.length; i++)
{
story.insertionPoints[-1].contents = data[i].heading + "\r"; // Use a newline to split the paragraph
story.insertionPoints[-2].appliedParagraphStyle = hdrStyle;
for (var j = 0; j < data[i].content.length; j++)
{
story.insertionPoints[-1].contents = data[i].content[j] + "\r"; // Use a newline to split the paragraph
story.insertionPoints[-2].appliedParagraphStyle = textStyle;
}
}
Обратите внимание, что здесь стоит инвертировать вставку содержимого и применение форматирования. Это так, что любое предыдущее "временное" форматирование очищается; применение стиля абзаца таким образом отменяет любые и все локальные переопределения. Поскольку вы должны применить стиль к предыдущему абзацу (тот, который был перед вставкой хард-возврата, который вы только что вставили), вы должны использовать insertionPoints[-2]
Вот.
Преимущества использования стилей перед локальным форматированием бесчисленны. Вы можете применить любое требуемое форматирование с помощью одной команды, безопасно удалить все локальное переопределенное форматирование и изменить любую часть форматирования глобально, если вас это не устраивает, вместо того, чтобы заново запускать сценарий с немного другими настройками.