Структура и стиль текста

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

На этой странице описано, как текст представлен в Slides API.

Последовательности текстовых элементов

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

Например, рассмотрим содержимое этого слайда — все содержится в одном текстовом поле:

скриншот простого слайда

На слайде выше есть одно текстовое поле, text поле которого содержит последовательность текстовых элементов, как показано на следующей диаграмме:

диаграмма, показывающая последовательность текстовых элементов

Более конкретно, эта последовательность текста представлена ​​в Slides API следующим образом:

"textElements": [ {
    "endIndex": 224,
    "paragraphMarker": { "style": {} }
  }, {
    "endIndex": 130,
    "textRun": { "content": "Li lingues differe in li grammatica e li vocabules. Omnicos directe al desirabilite de un nov ", "style": {} }
  }, {
    "endIndex": 143,
    "startIndex": 130,
    "textRun": { "content": "lingua franca", "style": { "italic": True } }
  }, {
    "endIndex": 224,
    "startIndex": 143,
    "textRun": { "content": ": solmen va esser necessi far:\n", "style": {} }
  }, {
    "endIndex": 243,
    "startIndex": 224,
    "paragraphMarker": {
      "style": { "indentStart": { "magnitude": 36, "unit": "PT" }, "direction": "LEFT_TO_RIGHT", "indentFirstLine": { "magnitude": 18, "unit": "PT" }, "spacingMode": "COLLAPSE_LISTS" },
      "bullet": { "listId": "foo123", "glyph": "\u25cf" }
    }
  }, {
    "endIndex": 243,
    "startIndex": 224,
    "textRun": { "content": "uniform grammatica\n", "style": {} }
  }, {
    "endIndex": 257,
    "startIndex": 243,
    "paragraphMarker": {
        "style": { "indentStart": { "magnitude": 36, "unit": "PT" }, "direction": "LEFT_TO_RIGHT", "indentFirstLine": { "magnitude": 18, "unit": "PT" }, "spacingMode": "COLLAPSE_LISTS" },
        "bullet": { "listId": "foo123", "glyph": "\u25cf" }
    }
}, {
    "endIndex": 257,
    "startIndex": 243,
    "textRun": { "content": "Pronunciation\n", "style": {} }
}, {
    "endIndex": 277,
    "startIndex": 257,
    "paragraphMarker": {
        "style": { "indentStart": { "magnitude": 36, "unit": "PT" }, "indentFirstLine": { "magnitude": 18, "unit": "PT" }, "spacingMode": "COLLAPSE_LISTS" },
        "bullet": { "listId": "foo123", "glyph": "\u25cf" }
    }
}, {
    "endIndex": 277,
    "startIndex": 257,
    "textRun": { "content": "plu sommun paroles.\n", "style": {} }
}, {
    "endIndex": 500,
    "startIndex": 277,
    "paragraphMarker": { "style": {} }
}, {
    "endIndex": 500,
    "startIndex": 277,
    "textRun": { "content": "Ka swu thefognay, tay waddeant varpa u inzo.\n", "style": {} }
}]

Содержимое TextElement

Каждый текстовый элемент содержит отсчитываемый от нуля начальный индекс и конечный индекс , которые описывают расположение элемента в полном тексте элемента страницы, а также один из следующих типов текстового объекта:

Тип текста Описание
Маркер абзаца Этот текстовый элемент представляет начало нового абзаца. Начальный и конечный индекс текстового элемента представляет собой полный диапазон абзаца, включая символ новой строки, завершающий абзац. Абзац никогда не перекрывает другой абзац. Абзацы всегда заканчиваются символом новой строки, поэтому в конце текстового содержимого фигуры или ячейки таблицы всегда есть новая строка.

Абзацы могут принадлежать к маркированным или нумерованным спискам. В этом случае содержимое поля ParagraphMarker.bullet включает идентификатор списка. Этот идентификатор ссылается на элемент списка, который существует внутри TextContent вместе с последовательностью TextElement . Абзацы в одном логическом списке будут ссылаться на один и тот же идентификатор списка.
ТекстРан Этот текстовый элемент представляет собой непрерывную строку текста, имеющую один и тот же текстовый стиль. Текстовые фрагменты никогда не пересекают границы абзацев: даже если текст, заканчивающий один абзац, имеет тот же стиль, что и текст, начинающий следующий абзац, содержимое разделяется после символа новой строки, образуя отдельные текстовые фрагменты.

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

Изменение текстового содержимого

Когда вам нужно изменить текст с помощью Slides API, вам не нужно явно создавать все соответствующие текстовые элементы. Вместо этого вы можете работать с текстом так же, как в редакторе слайдов: вставляя текст, удаляя диапазоны и обновляя стили для диапазонов. Эти операции неявно создают элементы ParagraphMarker и TextRun , необходимые для отражения ваших изменений.

Вставка текста

Вы можете вставить текст в индекс, используя запрос InsertTextRequest при вызове BatchUpdate . Поле insertionIndex этого метода указывает, куда вставить текст; вы можете вычислить этот индекс, используя поля начального и конечного индекса внутри текстовых элементов.

Вставка текста имеет некоторые побочные эффекты, повторяющие поведение редактора слайдов:

  • Вставка символа новой строки неявно создает новый абзац, создавая текстовый элемент ParagraphMarker , который начинается с индекса новой строки и заканчивается следующей новой строкой. Стиль абзаца, включая сведения о маркерах и списках, копируется из текущего абзаца в новый абзац.
  • Стиль вставляемых символов определяется автоматически, обычно сохраняя тот же стиль текста, который существовал в индексе вставки. В результате текст обычно вставляется в существующий TextRun по этому индексу. Вы можете обновить этот стиль позже, используя запрос UpdateTextStyle .

Удаление текста

Вы можете удалить диапазон текста, используя сообщение DeleteTextRequest в вызове BatchUpdate . Удаление текста предполагает некоторые тонкости:

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

Обновление стиля текста

Внешний вид текста на слайде определяется свойствами стиля текста:

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

Обновление стиля персонажа

Вы можете обновить стили символов, используя сообщение UpdateTextStyleRequest в вызове пакетного обновления .

Как и другие текстовые операции, стиль символов применяется к диапазону текста и неявно создает новые объекты TextRun по мере необходимости.

Установка некоторых стилей символов неявно обновляет другие связанные стили, чтобы они соответствовали поведению в редакторе слайдов. Например, добавление ссылки автоматически изменяет цвет переднего плана текста и свойства подчеркивания. Дополнительные сведения см. в справочной документации TextStyle .

Обновление стиля абзаца

Вы можете обновить стили абзаца, используя сообщение UpdateParagraphStyleRequest в вызове пакетного обновления .

API Slides поддерживает CreateParagraphBulletsRequest , который отражает функциональность наборов маркеров в редакторе слайдов для создания маркированных и нумерованных списков. Аналогично, DeleteParagraphBulletsRequest удаляет все существующие маркеры в абзацах.

Унаследованные стили

Некоторые фигуры, известные как заполнители , могут наследовать стили текста от других родительских фигур: см. заполнители , чтобы узнать больше о наследовании фигур в целом.

В этом разделе основное внимание уделяется тому, как работает наследование стилей для создания окончательных визуализированных стилей текста, отображаемых на слайде.

Представление стиля в заполнителях

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

  • Свойства текстовых элементов ParagraphMaker определяют форматирование абзаца.
  • Свойства текстовых элементов TextRun определяют форматирование символов.
  • Содержимое родительских заполнителей содержит восемь таких пар ParagraphMarker/TextRun (для поддержки восьми уровней вложенности списков).
  • Дочерний заполнитель наследует свои текстовые свойства по умолчанию от этих текстовых элементов в текстовом содержимом своего родителя.

На следующей диаграмме показан один из способов визуализации этих отношений:

Диаграмма дочерней фигуры, наследующей свойства текста

Первый ParagraphMarker/TextRun в родительской фигуре определяет большую часть наследуемого стиля текста; стиль в оставшихся семи парах влияет только на абзацы, находящиеся на более глубоко вложенных уровнях маркеров:

Пара родительских текстовых элементов Дочернее форматирование, которым оно управляет
ParagraphMarker первого абзаца
Первый TextRun
Стиль текста абзацев списка уровня 0 (крайних) и всех абзацев, не входящих в список.
ParagraphMarker второго абзаца
Второй TextRun
Стиль текста остальных (вложенных) уровней списков 1–7.
Маркер третьего ParagraphMarker
Третий TextRun
ParagraphMarker четвертого абзаца
Четвертый TextRun
ParagraphMarker пятого абзаца
Пятый TextRun
ParagraphMarker шестого абзаца
Шестой TextRun
ParagraphMarker седьмого абзаца
Седьмой TextRun
ParagraphMarker
Восьмой TextRun

Чтобы получить доступ к этим парам текстовых элементов, используйте их явный индекс в поле textElements , как показано во фрагменте ниже, где показана установка стиля по умолчанию (наследуемого) для уровня 0 и абзацев, не входящих в список:

"text": {
  "textElements": [  {
     "startIndex": 0,
     "endIndex": 1,
     "paragraphMarker": {
       "style": {  "alignment": "START",  ...  },
       "bullet": {  "nestingLevel": 0,  ...  }
     }
   },{
     "startIndex": 0,
     "endIndex": 1,
     "textRun": {
       "content": "\n",
       "style": {  "foregroundColor": {  "opaqueColor": {  "themeColor": "DARK1"  }  },  }
     }
   },{
     ...
   } ]
 }

Обратите внимание, что поле content TextRun родительской фигуры всегда состоит из одного символа новой строки.

Унаследованные стили могут быть переопределены.

Дочерняя фигура может указывать свойства стиля для элементов ParagraphMarker и TextRun в своем содержимом. Эти локально заданные свойства переопределяют любые унаследованные свойства в своей локальной области. Элементы, для которых не указан какой-либо стиль, будут использовать соответствующий стиль, унаследованный от родительского элемента.

Удаление явного свойства стиля из дочерней фигуры, чтобы оно больше не было задано, приведет к его наследованию от родительской фигуры.

Пример

Учитывая наследование, показанное на диаграмме выше, предположим, что фигура ParentPlaceholder имеет следующее текстовое содержимое:

"text": {
  "textElements": [
    { "startIndex": 0,  "endIndex": 1,
      "paragraphMarker": {
        "style": {"alignment": "START", ...},
        "bullet": {"nestingLevel": 0, ...}
      }
    },
    { "startIndex": 0,  "endIndex": 1,
      "textRun": {
        "content": "\n",
        "style": {"foregroundColor": {"opaqueColor": {"themeColor": "DARK1"} }, }
        ...
      }
    },
    { "startIndex": 1,  "endIndex": 2,
      "paragraphMarker": {
        "style": {"alignment": "END", ...},
        "bullet": {"nestingLevel": 1, ...}
      }
    },
    { "startIndex": 1,  "endIndex": 2,
      "textRun": {
        "content": "\n",
        "style": {"foregroundColor": {"opaqueColor": {"themeColor": "LIGHT1"} }, ...}
      }
    },
   ...
  ]
}

Предположим, что фигура ChildPlaceholder имеет следующее текстовое содержимое:

"text": {
  "textElements": [
    { "startIndex": 0,  "endIndex": 1,
      "paragraphMarker": {
        "style": {},
      }
    },
    { "startIndex": 0,  "endIndex": 1,
      "textRun": {
        "content": "This is my first paragraph\n",
        "style": {},
      }
      ...
    },
    {  "startIndex": 1,  "endIndex": 2,
      "paragraphMarker": {
        "style": {},
        "bullet": {
          "nestingLevel": 1,
          "listId": "someListId",
          "glyph": "●"
        }
      }
    },
    { "startIndex": 1,  "endIndex": 2,
      "textRun": {
        "content": "This paragraph is in a list\n",
        "style": {},
        ...
      }
    }
  ]
}

Это приводит к результатам, описанным в следующих параграфах.

Наследование стиля для простого абзаца

Первый абзац дочерней фигуры, включающий текст «Это мой первый абзац», представляет собой простой абзац (не в списке). Ни один элемент в его текстовом содержимом не задает никаких свойств стиля, поэтому он наследует все стили символов и абзацев от своего родителя. Это приводит к следующему рендерингу:

  • Текст: «Это мой первый абзац» — это отображаемый текст. Сам текст никогда не наследуется.
  • Выравнивание: текст отображается с выравниванием START , унаследованным от первого ParagraphMarker родительского объекта.
  • Цвет переднего плана: текст отображается с цветом переднего плана DARK1 , унаследованным от первого TextRun родительского объекта.

Наследование стиля для абзаца списка

Следующий абзац, включающий текст «Этот абзац находится в списке», находится в маркированном списке на уровне вложенности 1, поскольку для соответствующего ему ParagraphMarker поле bullet установлено на этот уровень. В результате он наследует стиль текста и абзаца от уровня вложенности 1 в родительском элементе. В результате получается следующий рендеринг:

  • Текст: «Этот абзац находится в списке» — это отображаемый текст. Сам текст никогда не наследуется.
  • Выравнивание: текст отображается с выравниванием «END», унаследованным от второго ParagraphMarker родительского объекта.
  • Цвет переднего плана: текст отображается с цветом переднего плана текста LIGHT1 , унаследованным от второго TextRun родительского объекта.

Взаимодействие между обновлением и наследованием стилей текста и абзацев

Стили текста, которые не заданы в дочерней фигуре, наследуют значения от ее родительской фигуры. Стили текста, установленные в дочернем элементе, будут «переопределять» родительские значения в некоторой локальной области.

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

Это не влияет на внешний вид текста сразу после обновления, но может иметь значение, если вы позже обновите абзац или стиль текста в родительском заполнителе. Такое поведение наследования соответствует поведению редактора слайдов, поэтому вы можете поэкспериментировать с результатами изменения стиля, прежде чем работать с API.

Пример

Рассмотрим определения ChildPlaceholder и ParentPlaceholder в предыдущем примере .

Теперь предположим, что вы отправили этот UpdateTextStyleRequest :

{ "updateTextStyle": {
    "objectId": "ChildPlaceholder",
    "style": {"foregroundColor": {"opaqueColor": {"themeColor": "DARK1"} }, },
    "textRange": { "type": "ALL" },
    "fields": "foregroundColor"
  }
}

Этот запрос пытается установить цвет переднего плана DARK1 для всего текста ChildPlaceholder, используя маску поля , чтобы указать, что должен меняться только цвет переднего плана элемента. Этот запрос имеет следующие результаты:

  • Первый абзац: новый foregroundColor соответствует унаследованному foregroundColor , поэтому этот стиль не изменился и продолжает наследоваться.
  • Второй абзац: новый foregroundColor не соответствует унаследованному foregroundColor , поэтому цвет переднего плана второго абзаца обновляется до DARK1 .

Текстовое содержимое ChildPlaceholder теперь имеет следующий вид:

"text": {
  "textElements": [
    { "startIndex": 0,  "endIndex": 1,
      "paragraphMarker": {
        "style": {},
      }
    },
    { "startIndex": 0,  "endIndex": 1,
      "textRun": {
        "content": "This is my first paragraph\n",
        "style": {},
      }
      ...
    },
    { "startIndex": 1,  "endIndex": 2,
      "paragraphMarker": {
        "style": {},
        "bullet": {"nestingLevel": 1, "listId": "someListId", "glyph": "●" }
      }
    },
    { "startIndex": 1,  "endIndex": 2,
      "textRun": {
        "content": "This paragraph is in a list\n",
        "style": {"foregroundColor": {"opaqueColor": {"themeColor": "DARK1"} }, },
        ...
      }
    }
  ]
}

Стиль текста в виде пули

Как и обычный текст, маркеры имеют текстовый стиль, который управляет отображением глифа. Эти стили текста нельзя изменить напрямую с помощью Slides API. Однако если вы используете UpdateTextStyleRequest для обновления всего абзаца, включающего маркер, API Slides обновляет стиль текста глифа маркера в соответствии с ним.

Стили текста маркированных глифов следуют несколько иной иерархии наследования, чем обычные текстовые стили.

  1. Маркер на определенном уровне вложенности сначала наследуется от TextStyle , установленного в поле NestingLevel.bullet_style внутри объекта List маркера.
  2. Затем он наследуется от соответствующего NestingLevel.bullet_style в родительском заполнителе List .
  3. Наконец, он пытается наследовать оставшиеся родительские объекты-заполнители.