Cấu trúc và định kiểu văn bản

Trong API Trang trình bày, văn bản có thể được chứa trong các hình dạng hoặc trong các ô của bảng. Trước khi có thể thao tác và tạo kiểu cho văn bản, bạn cần nắm được cấu trúc của văn bản đó và cách hoạt động của tính năng định kiểu.

Trang này mô tả cách văn bản được trình bày trong API Trang trình bày.

Trình tự của các thành phần văn bản

Văn bản được chứa trong một hình hoặc ô trong bảng được tạo thành từ một chuỗi TextElement cấu trúc. Trình tự này thể hiện cấu trúc của văn bản theo thứ tự xuất hiện từ đầu đến cuối.

Ví dụ: hãy xem xét nội dung của trang trình bày này — tất cả có trong một trang trình bày hộp văn bản:

ảnh chụp màn hình của một trang trình bày đơn giản

Trang trình bày trên có một hộp văn bản, trong đó trường text chứa một trình tự gồm các phần tử văn bản như được minh hoạ trong sơ đồ sau:

sơ đồ cho thấy một chuỗi các thành phần văn bản

Cụ thể hơn, chuỗi văn bản này được thể hiện trong API Trang trình bày dưới dạng sau:

"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": {} }
}]

Nội dung TextElement

Mỗi phần tử văn bản chứa chỉ mục bắt đầuchỉ mục kết thúc dựa trên giá trị 0, mô tả vị trí của phần tử trong toàn bộ văn bản của trang cùng với một trong các loại đối tượng văn bản sau:

Loại văn bản Mô tả
ParagraphMarker Phần tử văn bản này đại diện cho phần đầu của một đoạn mới. Chỉ mục bắt đầu và kết thúc của phần tử văn bản đại diện cho toàn bộ đoạn văn bản, bao gồm cả ký tự dòng mới kết thúc đoạn. Một đoạn không bao giờ chồng chéo với đoạn khác. Các đoạn luôn kết thúc bằng ký tự dòng mới, nên luôn có một dòng mới ở cuối nội dung văn bản của một hình dạng hoặc ô trong bảng.

Các đoạn có thể thuộc danh sách có dấu đầu dòng hoặc danh sách được đánh số. Nếu có, nội dung trường ParagraphMarker.bullet sẽ bao gồm mã danh sách. Mã nhận dạng này tham chiếu đến một phần tử danh sách tồn tại bên trong TextContent cùng với trình tự TextElement. Các đoạn trong cùng một danh sách logic sẽ đề cập đến cùng một mã danh sách.
TextRun Phần tử văn bản này đại diện cho một chuỗi văn bản liền kề và tất cả đều có cùng một kiểu văn bản. Văn bản không bao giờ chạy qua ranh giới của đoạn: ngay cả khi văn bản kết thúc một đoạn có cùng kiểu như văn bản bắt đầu đoạn tiếp theo, nội dung sẽ được phân tách sau khi ký tự dòng mới tạo thành các đoạn văn bản riêng biệt.

Nếu bạn cần xử lý chuỗi văn bản đầy đủ bên trong một thành phần trang, hãy lặp lại qua tất cả các thành phần văn bản, nối các chuỗi có trong tất cả các lần chạy văn bản.
AutoText Văn bản tự động đề cập đến những vị trí trong văn bản tự động thay đổi tuỳ thuộc vào ngữ cảnh. Trong Trang trình bày, giá trị này được dùng để biểu thị số của trang trình bày hiện tại trong văn bản.

Sửa đổi nội dung văn bản

Khi cần sửa đổi văn bản bằng API Trang trình bày, bạn không cần phải làm rõ tạo tất cả các thành phần văn bản thích hợp. Thay vào đó, bạn có thể thao tác trên văn bản như bạn sẽ thực hiện trong trình chỉnh sửa Trang trình bày: bằng cách chèn văn bản, xoá dải ô và cập nhật kiểu trên các dải ô. Các thao tác này ngầm tạo ParagraphMarkerTextRun phần tử nếu cần để phản ánh các thay đổi của bạn.

Chèn văn bản

Bạn có thể chèn văn bản tại một chỉ mục bằng cách sử dụng InsertTextRequest yêu cầu trong cuộc gọi đến batchUpdate. Chiến dịch này trường insertionIndex của phương thức chỉ định vị trí chèn văn bản; bạn có thể tính toán chỉ mục này bằng cách sử dụng trường chỉ mục bắt đầu và chỉ mục kết thúc bên trong phần tử văn bản.

Tính năng chèn văn bản có một số hiệu ứng phụ phản ánh hoạt động của Trang trình bày người chỉnh sửa:

  • Việc chèn ký tự dòng mới sẽ ngầm tạo ra một đoạn mới, tạo một phần tử văn bản ParagraphMarker bắt đầu tại chỉ mục của dòng mới và kết thúc vào dòng mới sau đây. Kiểu đoạn văn bản, bao gồm cả dấu đầu dòng và chi tiết danh sách — được sao chép từ đoạn hiện tại sang đoạn mới đoạn.
  • Kiểu ký tự được chèn được xác định tự động, thường giữ nguyên kiểu văn bản đã tồn tại tại chỉ mục chèn. Do đó, văn bản thường được chèn vào TextRun hiện có tại thời điểm đó chỉ mục. Bạn có thể cập nhật kiểu này sau bằng cách sử dụng UpdateTextStyle của bạn.

Đang xoá văn bản

Bạn có thể xoá một dải văn bản bằng cách sử dụng DeleteTextRequest trong cuộc gọi tới batchUpdate. Việc xoá văn bản cũng cần lưu ý một số điểm tinh tế:

  • Thao tác xoá qua ranh giới của đoạn sẽ hợp nhất hai đoạn xoá phần tử văn bản ParagraphMarker phân tách.
  • Đoạn được hợp nhất mới sẽ sử dụng kiểu đoạn kết hợp, kiểu khớp trong trình chỉnh sửa Trang trình bày.
  • Thao tác xoá có phạm vi bao gồm một lần chạy văn bản sẽ xoá tất cả nội dung khỏi đồng thời văn bản cũng sẽ bị xoá.
  • Thao tác xoá có phạm vi bao gồm phần tử AutoText sẽ xoá Phần tử AutoText.

Đang cập nhật kiểu văn bản

Giao diện văn bản được kết xuất trong trang trình bày được xác định theo kiểu văn bản thuộc tính:

  • Các kiểu đoạn như thụt lề, căn chỉnh và ký tự đầu dòng được xác định theo thuộc tính trên dấu đánh dấu đoạn.
  • Các kiểu ký tự như in đậm, in nghiêng và gạch dưới, được xác định bằng các thuộc tính trên từng văn bản chạy riêng.

Đang cập nhật kiểu nhân vật

Bạn có thể cập nhật kiểu ký tự bằng cách sử dụng UpdateTextStyleRequest trong cuộc gọi tới batchUpdate.

Giống như các thao tác văn bản khác, kiểu ký tự được áp dụng cho một dải ô văn bản và ngầm tạo đối tượng TextRun mới khi cần.

Việc đặt một số kiểu ký tự sẽ ngầm cập nhật các kiểu có liên quan khác để khớp hành vi trong trình chỉnh sửa Trang trình bày. Ví dụ: tự động thêm một đường liên kết thay đổi màu nền trước của văn bản và các thuộc tính gạch chân. Xem TextStyle tài liệu tham khảo để biết thêm chi tiết.

Đang cập nhật kiểu đoạn

Bạn có thể cập nhật kiểu đoạn bằng cách sử dụng UpdateParagraphStyleRequest trong cuộc gọi tới batchUpdate.

API Trang trình bày hỗ trợ CreateParagraphBulletsRequest phản ánh chức năng của các giá trị đặt trước cho dấu đầu dòng trong trình chỉnh sửa Trang trình bày tạo danh sách có dấu đầu dòng và được đánh số. Tương tự như DeleteParagraphBulletsRequest xoá mọi dấu đầu dòng hiện có trên đoạn.

Kiểu kế thừa

Một số hình dạng (còn gọi là phần giữ chỗ) có thể kế thừa kiểu văn bản từ các hình dạng mẹ khác hình dạng: xem phần giữ chỗ để tìm hiểu thêm về tính kế thừa hình dạng nói chung.

Phần này tập trung vào cách hoạt động của tính kế thừa kiểu để tạo kiểu văn bản đã kết xuất hiện trên một trang trình bày.

Kiểu trình bày trong phần giữ chỗ

Phần trên phần giữ chỗ mô tả cách hoạt động của tính kế thừa giữa hình dạng mẹ và hình dạng con. Kế thừa kiểu văn bản được xử lý bằng các tính năng bổ sung trong mô hình kế thừa:

  • Thuộc tính của ParagraphMaker các phần tử văn bản xác định định dạng đoạn.
  • Thuộc tính của TextRun các phần tử văn bản xác định định dạng ký tự.
  • Nội dung của phần giữ chỗ mẹ chứa 8 đoạn mã ĐoạnMarker/TextRun như vậy các cặp (để hỗ trợ 8 cấp độ lồng danh sách).
  • Phần giữ chỗ con kế thừa các thuộc tính văn bản mặc định của văn bản này trong nội dung văn bản của phần tử mẹ.

Sơ đồ dưới đây cho thấy một cách để trực quan hoá các mối quan hệ này:

sơ đồ hình dạng con kế thừa các thuộc tính văn bản

ĐoạnMarker/TextRun đầu tiên trong hình dạng mẹ xác định hầu hết định kiểu văn bản kế thừa; kiểu trong 7 cặp còn lại chỉ ảnh hưởng đến các đoạn ở cấp độ dấu đầu dòng được lồng ngày càng sâu hơn:

Cặp phần tử văn bản mẹ Định dạng con mà hệ thống kiểm soát
ParagraphMarker
TextRun đầu tiên
Kiểu văn bản của danh sách cấp 0 (ngoài cùng) và tất cả các đoạn không có danh sách.
Thứ hai ParagraphMarker
thứ hai TextRun
Kiểu văn bản còn lại (lồng nhau) cấp danh sách từ 1 đến 7
Thứ ba ParagraphMarker
TextRun thứ ba
Khu thứ tư ParagraphMarker
thứ tư TextRun
Thứ năm ParagraphMarker
Ngày TextRun thứ năm
Thứ sáu ParagraphMarker
Thứ sáu TextRun
Ngày thứ bảy ParagraphMarker
thứ bảy TextRun
Thứ tám ParagraphMarker
thứ tám TextRun

Để truy cập vào các cặp thành phần văn bản này, hãy sử dụng chỉ mục rõ ràng của chúng trong Trường textElements như minh hoạ trong đoạn mã bên dưới, cho biết việc cài đặt định kiểu mặc định (có thể kế thừa) cho các đoạn cấp 0 và các đoạn không phải danh sách:

"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"  }  },  }
     }
   },{
     ...
   } ]
 }

Lưu ý rằng trường content trong TextRun của hình dạng mẹ luôn bao gồm một ký tự dòng mới.

Có thể ghi đè kiểu kế thừa

Hình dạng con có thể chỉ định các thuộc tính định kiểu trên ParagraphMarkerTextRun trong nội dung. Các thuộc tính được chỉ định cục bộ này sẽ ghi đè mọi thuộc tính các thuộc tính được kế thừa trong phạm vi địa phương của chúng. Các phần tử không chỉ định bất kỳ kiểu sẽ sử dụng kiểu tương ứng kế thừa từ kiểu gốc.

Xoá một thuộc tính kiểu rõ ràng khỏi hình dạng con để thuộc tính đó không còn tồn tại sẽ khiến nó kế thừa từ phần tử mẹ.

Ví dụ:

Với tính kế thừa như trong biểu đồ trên, giả sử hình dạng ParentPlaceholder có nội dung văn bản sau:

"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"} }, ...}
      }
    },
   ...
  ]
}

Và giả sử hình dạng ChildPlaceholder có nội dung văn bản sau:

"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": {},
        ...
      }
    }
  ]
}

Điều này dẫn đến kết quả được mô tả trong các đoạn sau.

Tính kế thừa kiểu cho một đoạn văn bản thuần tuý

Đoạn đầu tiên của hình dạng con, bao gồm text "Đây là đoạn đầu tiên của tôi", là một đoạn văn bản thuần tuý (không phải trong danh sách). Không có phần tử nào trong nội dung văn bản chỉ định bất kỳ thuộc tính kiểu nào, để nó kế thừa tất cả các kiểu ký tự và đoạn văn bản của thành phần mẹ của nó. Điều này gây ra các kết xuất sau:

  • Văn bản: "Đây là đoạn đầu tiên của tôi" là văn bản được hiển thị. Bản thân văn bản không bao giờ được kế thừa.
  • Căn chỉnh: Văn bản được hiển thị với căn chỉnh START, kế thừa từ ParagraphMarker đầu tiên của nhà xuất bản mẹ.
  • Màu nền trước: Văn bản được kết xuất bằng màu nền trước DARK1, được kế thừa từ TextRun đầu tiên của phần tử mẹ.

Kế thừa kiểu cho đoạn danh sách

Đoạn tiếp theo, bao gồm văn bản "Đoạn này nằm trong danh sách", nằm trong danh sách có dấu đầu dòng ở cấp độ lồng 1, vì ParagraphMarker tương ứng có trường bullet được đặt ở cấp này. Do đó, tính năng này kế thừa văn bản và đoạn văn bản từ mức lồng cấp 1 trong phần tử mẹ. Điều này dẫn đến việc kết xuất hình ảnh sau:

  • Văn bản: "Đoạn này nằm trong danh sách" là văn bản được hiển thị. Bản thân văn bản không bao giờ được kế thừa.
  • Căn chỉnh: Văn bản được hiển thị bằng "END" căn chỉnh, kế thừa từ ParagraphMarker thứ hai của nhà xuất bản mẹ.
  • Màu nền trước: Văn bản được hiển thị bằng màu nền trước của văn bản LIGHT1, được kế thừa từ TextRun thứ hai của nhà xuất bản mẹ.

Tương tác giữa việc cập nhật và kế thừa kiểu văn bản và đoạn văn

Kiểu văn bản không được thiết lập trong hình dạng con sẽ kế thừa các giá trị của cha mẹ. Kiểu văn bản được đặt trong phần tử con sẽ "ghi đè" các giá trị gốc ở một số phạm vi cục bộ.

Bạn có thể sử dụng UpdateTextStyleRequest huỷ thiết lập kiểu văn bản của hình dạng con để hình dạng con đó không còn có giá trị ghi đè cục bộ và do đó kế thừa các chuỗi văn bản từ hình dạng mẹ. Ngoài ra, việc cập nhật kiểu văn bản của phần tử con khớp với giá trị được kế thừa từ phần tử mẹ huỷ đặt kiểu ngầm ẩn để sử dụng giá trị kế thừa.

Điều này không ảnh hưởng đến hình ảnh hình thức của văn bản ngay sau khi cập nhật, nhưng điều này có thể quan trọng nếu sau này cập nhật một đoạn văn hoặc kiểu văn bản trong phần giữ chỗ gốc. Cơ chế kế thừa này phù hợp với hành vi của trình chỉnh sửa Trang trình bày để bạn có thể thử nghiệm kết quả của những thay đổi về kiểu trước khi xử lý API.

Ví dụ:

Hãy xem xét các định nghĩa trong ví dụ trước cho ChildPlaceholderParentPlaceholder.

Bây giờ, giả sử bạn gửi UpdateTextStyleRequest:

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

Yêu cầu này cố gắng đặt DARK1foregroundColor thành tất cả Văn bản của ChildPlaceholder, sử dụng fieldMask để chỉ định rằng chỉ có màu nền trước của phần tử mới thay đổi. Chiến dịch này yêu cầu sẽ có những kết quả sau:

  • Đoạn đầu tiên: foregroundColor mới khớp với đoạn văn bản kế thừa foregroundColor, vì vậy, kiểu này không thay đổi và vẫn kế thừa.
  • Đoạn thứ hai: foregroundColor mới không khớp với đoạn mã được kế thừa foregroundColor, do đó màu nền trước của đoạn thứ hai được cập nhật thành DARK1

Nội dung văn bản của ChildPlaceholder hiện là:

"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"} }, },
        ...
      }
    }
  ]
}

Kiểu văn bản ký tự đầu dòng

Giống như văn bản thông thường, ký tự gạch đầu dòng có một kiểu văn bản kiểm soát cách ký tự được kết xuất. Không thể sửa đổi các kiểu văn bản này bằng API Trang trình bày trực tiếp. Tuy nhiên, nếu bạn sử dụng một UpdateTextStyleRequest để cập nhật một đoạn hoàn chỉnh có chứa dấu đầu dòng, API Trang trình bày sẽ cập nhật kiểu văn bản của ký tự gạch đầu dòng cho phù hợp.

Kiểu văn bản chèn dấu đầu dòng tuân theo hệ phân cấp kế thừa hơi khác so với kiểu văn bản thông thường.

  1. Dấu đầu dòng ở một cấp độ lồng nhất định sẽ kế thừa từ tập hợp TextStyle trong trường NestingLevel.bullet_style bên trong đối tượng List của dấu đầu dòng.
  2. Lần tiếp theo sẽ kế thừa từ NestingLevel.bullet_style tương ứng trong List của phần giữ chỗ gốc.
  3. Cuối cùng, nó tìm cách kế thừa từ các đối tượng phần giữ chỗ mẹ còn lại.