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] Вот.

Преимущества использования стилей перед локальным форматированием бесчисленны. Вы можете применить любое требуемое форматирование с помощью одной команды, безопасно удалить все локальное переопределенное форматирование и изменить любую часть форматирования глобально, если вас это не устраивает, вместо того, чтобы заново запускать сценарий с немного другими настройками.

Другие вопросы по тегам