or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

comments.mddocument-operations.mdimages-shapes.mdindex.mdsections-layout.mdstyles-formatting.mdtables.mdtext-paragraphs.md

comments.mddocs/

0

# Comments

1

2

Document commenting system for adding and managing comments anchored to specific text ranges. Provides collaborative features for document review and annotation.

3

4

## Capabilities

5

6

### Comment Management

7

8

Access and manage the document comments collection.

9

10

```python { .api }

11

class Document:

12

@property

13

def comments(self):

14

"""Collection of all comments in document.

15

16

Returns:

17

Comments: Comments collection object

18

"""

19

20

def add_comment(self, runs, text='', author='', initials=''):

21

"""Add a comment to the document.

22

23

Args:

24

runs (Run or list[Run]): Run or sequence of runs to anchor comment to

25

text (str, optional): Comment text content

26

author (str, optional): Comment author name

27

initials (str, optional): Author initials

28

29

Returns:

30

Comment: New comment object

31

"""

32

33

class Comments:

34

def add_comment(self, runs, text='', author='', initials=''):

35

"""Add a comment anchored to specified runs.

36

37

Args:

38

runs (Run or list[Run]): Run or sequence of runs to comment on

39

text (str, optional): Comment text content

40

author (str, optional): Comment author name

41

initials (str, optional): Author initials

42

43

Returns:

44

Comment: New comment object

45

"""

46

47

def __len__(self):

48

"""Number of comments in collection."""

49

50

def __iter__(self):

51

"""Iterate over comments."""

52

53

def __getitem__(self, index):

54

"""Access comment by index."""

55

```

56

57

**Usage Examples:**

58

59

```python

60

# Access comments collection

61

comments = doc.comments

62

print(f"Document has {len(comments)} comments")

63

64

# Add comment to a single run

65

para = doc.add_paragraph('This text will have a comment.')

66

run = para.runs[0]

67

comment = doc.add_comment(run, 'This is a comment', author='John Doe', initials='JD')

68

69

# Add comment through comments collection

70

comment2 = comments.add_comment(run, 'Another comment', author='Jane Smith')

71

72

# Iterate through all comments

73

for i, comment in enumerate(comments):

74

print(f"Comment {i+1}: {comment.text} by {comment.author}")

75

```

76

77

### Creating Comments

78

79

Add comments to specific text ranges with various anchoring options.

80

81

**Usage Examples:**

82

83

```python

84

# Add comment to single run

85

para = doc.add_paragraph('Text with comment.')

86

run = para.runs[0]

87

comment = doc.add_comment(run, 'Review this text', author='Reviewer')

88

89

# Add comment to multiple runs (text span)

90

para = doc.add_paragraph()

91

run1 = para.add_run('Start of ')

92

run2 = para.add_run('commented text ')

93

run3 = para.add_run('end.')

94

95

# Comment spans multiple runs

96

commented_runs = [run1, run2]

97

comment = doc.add_comment(commented_runs, 'This spans multiple runs',

98

author='Editor', initials='ED')

99

100

# Add comment with detailed information

101

para = doc.add_paragraph('Important information here.')

102

run = para.runs[0]

103

comment = doc.add_comment(

104

run,

105

'Please verify this information with the latest data.',

106

author='Data Analyst',

107

initials='DA'

108

)

109

110

# Add empty comment (to be filled later)

111

comment = doc.add_comment(run, author='Placeholder')

112

```

113

114

### Comment Properties

115

116

Access and manage comment properties and content.

117

118

```python { .api }

119

class Comment:

120

@property

121

def text(self):

122

"""Comment text content (read-only).

123

124

Returns:

125

str: Plain text content of all comment paragraphs

126

"""

127

128

@property

129

def author(self):

130

"""Comment author (read-only).

131

132

Returns:

133

str: Author name

134

"""

135

136

@property

137

def initials(self):

138

"""Author initials (read-only).

139

140

Returns:

141

str: Author initials

142

"""

143

144

@property

145

def paragraphs(self):

146

"""Paragraphs in the comment.

147

148

Returns:

149

list[Paragraph]: List of paragraph objects in comment

150

"""

151

152

@property

153

def tables(self):

154

"""Tables in the comment.

155

156

Returns:

157

list[Table]: List of table objects in comment

158

"""

159

160

def add_paragraph(self, text='', style=None):

161

"""Add a paragraph to the comment.

162

163

Args:

164

text (str, optional): Paragraph text

165

style (str or ParagraphStyle, optional): Paragraph style

166

167

Returns:

168

Paragraph: New paragraph object

169

"""

170

171

def add_table(self, rows, cols):

172

"""Add a table to the comment.

173

174

Args:

175

rows (int): Number of initial rows

176

cols (int): Number of initial columns

177

178

Returns:

179

Table: New table object

180

"""

181

```

182

183

**Usage Examples:**

184

185

```python

186

# Create comment and access properties

187

para = doc.add_paragraph('Commented text')

188

run = para.runs[0]

189

comment = doc.add_comment(run, 'Initial comment', author='John Doe', initials='JD')

190

191

# Access comment properties

192

print(f"Author: {comment.author}")

193

print(f"Initials: {comment.initials}")

194

print(f"Text: {comment.text}")

195

196

# Add additional content to comment

197

additional_para = comment.add_paragraph('Additional comment details.')

198

additional_para.runs[0].italic = True

199

200

# Add formatted content

201

formatted_para = comment.add_paragraph()

202

formatted_para.add_run('Bold comment text').bold = True

203

formatted_para.add_run(' and normal text.')

204

205

# Add table to comment

206

comment_table = comment.add_table(rows=2, cols=2)

207

comment_table.cell(0, 0).text = 'Issue'

208

comment_table.cell(0, 1).text = 'Status'

209

comment_table.cell(1, 0).text = 'Grammar'

210

comment_table.cell(1, 1).text = 'Fixed'

211

212

# Access all paragraphs in comment

213

for para in comment.paragraphs:

214

print(f"Comment paragraph: {para.text}")

215

```

216

217

### Advanced Comment Usage

218

219

Complex scenarios for document review and collaboration.

220

221

**Usage Examples:**

222

223

```python

224

# Create review workflow with multiple comments

225

def add_review_comment(run, issue_type, description, reviewer):

226

"""Add structured review comment."""

227

comment = doc.add_comment(run, '', author=reviewer)

228

229

# Add issue type header

230

header = comment.add_paragraph(f"{issue_type.upper()}", style='Strong')

231

232

# Add description

233

desc_para = comment.add_paragraph(description)

234

235

# Add reviewer signature

236

sig_para = comment.add_paragraph(f"- {reviewer}")

237

sig_para.runs[0].italic = True

238

239

return comment

240

241

# Usage of review function

242

para = doc.add_paragraph('This sentence has a potential issue.')

243

run = para.runs[0]

244

245

# Add different types of review comments

246

add_review_comment(run, 'Grammar', 'Check subject-verb agreement', 'Copy Editor')

247

add_review_comment(run, 'Fact Check', 'Verify statistics mentioned', 'Research Team')

248

add_review_comment(run, 'Style', 'Consider more concise wording', 'Style Guide Team')

249

250

# Create comment thread simulation

251

base_comment = doc.add_comment(run, 'Original comment', author='Author')

252

reply_para = base_comment.add_paragraph('Reply to comment')

253

reply_para.add_run(' - Reviewer Response').italic = True

254

255

# Add comment with action items

256

action_comment = doc.add_comment(run, '', author='Project Manager')

257

action_comment.add_paragraph('Action Items:')

258

259

action_table = action_comment.add_table(rows=3, cols=3)

260

headers = ['Task', 'Assignee', 'Due Date']

261

for i, header in enumerate(headers):

262

action_table.cell(0, i).text = header

263

action_table.cell(0, i).paragraphs[0].runs[0].bold = True

264

265

# Add action items

266

tasks = [

267

['Revise paragraph', 'Writer', '2024-01-15'],

268

['Review changes', 'Editor', '2024-01-17']

269

]

270

271

for row_idx, task_data in enumerate(tasks, 1):

272

for col_idx, data in enumerate(task_data):

273

action_table.cell(row_idx, col_idx).text = data

274

```

275

276

### Comment Analysis and Reporting

277

278

Analyze and report on document comments.

279

280

**Usage Examples:**

281

282

```python

283

def analyze_comments(doc):

284

"""Analyze document comments and generate report."""

285

comments = doc.comments

286

287

if len(comments) == 0:

288

print("No comments in document")

289

return

290

291

# Count comments by author

292

author_counts = {}

293

for comment in comments:

294

author = comment.author or 'Unknown'

295

author_counts[author] = author_counts.get(author, 0) + 1

296

297

print(f"Total comments: {len(comments)}")

298

print("\nComments by author:")

299

for author, count in author_counts.items():

300

print(f" {author}: {count}")

301

302

# List all comments

303

print("\nAll comments:")

304

for i, comment in enumerate(comments, 1):

305

print(f"{i}. [{comment.author or 'Unknown'}] {comment.text[:100]}...")

306

307

# Usage

308

analyze_comments(doc)

309

310

def extract_comment_text(doc):

311

"""Extract all comment text for analysis."""

312

all_comment_text = []

313

314

for comment in doc.comments:

315

# Get main comment text

316

main_text = comment.text

317

318

# Get text from all paragraphs (more detailed)

319

detailed_text = '\n'.join(para.text for para in comment.paragraphs)

320

321

all_comment_text.append({

322

'author': comment.author,

323

'initials': comment.initials,

324

'text': main_text,

325

'detailed_text': detailed_text

326

})

327

328

return all_comment_text

329

330

# Extract comment data

331

comment_data = extract_comment_text(doc)

332

for comment_info in comment_data:

333

print(f"Author: {comment_info['author']}")

334

print(f"Text: {comment_info['text']}")

335

print("---")

336

```

337

338

### Programmatic Comment Creation

339

340

Create comments programmatically for automated review processes.

341

342

**Usage Examples:**

343

344

```python

345

import re

346

347

def add_spell_check_comments(doc):

348

"""Add comments for potential spelling issues."""

349

# Simple spell check simulation

350

potential_errors = ['teh', 'recieve', 'occured', 'seperate']

351

352

for para in doc.paragraphs:

353

for error in potential_errors:

354

if error in para.text.lower():

355

# Find the run containing the error

356

for run in para.runs:

357

if error in run.text.lower():

358

comment = doc.add_comment(

359

run,

360

f'Possible spelling error: "{error}"',

361

author='Spell Checker',

362

initials='SC'

363

)

364

break

365

366

def add_length_comments(doc, max_sentence_length=25):

367

"""Add comments for overly long sentences."""

368

for para in doc.paragraphs:

369

sentences = re.split(r'[.!?]+', para.text)

370

for sentence in sentences:

371

words = sentence.strip().split()

372

if len(words) > max_sentence_length:

373

# Find run containing long sentence

374

for run in para.runs:

375

if sentence.strip() in run.text:

376

comment = doc.add_comment(

377

run,

378

f'Long sentence ({len(words)} words). Consider breaking up.',

379

author='Style Checker',

380

initials='ST'

381

)

382

break

383

384

# Apply automated commenting

385

add_spell_check_comments(doc)

386

add_length_comments(doc)

387

388

def add_consistency_comments(doc, style_guide):

389

"""Add comments for style guide violations."""

390

violations = {

391

'passive_voice': r'\b(was|were|is|are|been)\s+\w+ed\b',

392

'weak_words': r'\b(very|really|quite|rather)\b',

393

'contractions': r"\b\w+'\w+\b"

394

}

395

396

for para in doc.paragraphs:

397

for violation_type, pattern in violations.items():

398

matches = re.finditer(pattern, para.text, re.IGNORECASE)

399

for match in matches:

400

# Find the run containing the match

401

for run in para.runs:

402

if match.group() in run.text:

403

comment = doc.add_comment(

404

run,

405

f'Style guide: {violation_type.replace("_", " ").title()}',

406

author='Style Guide Bot',

407

initials='SG'

408

)

409

break

410

411

# Apply style guide checking

412

style_guide = {} # Style guide configuration

413

add_consistency_comments(doc, style_guide)

414

```

415

416

## Usage Patterns

417

418

### Document Review Workflow

419

420

```python

421

# Complete document review workflow

422

def setup_document_review(doc, reviewers):

423

"""Set up document for review process."""

424

# Add review instructions in document

425

instructions = doc.add_paragraph('REVIEW INSTRUCTIONS:', style='Strong')

426

doc.add_paragraph('Please add comments to sections that need attention.')

427

doc.add_paragraph('Use your initials when adding comments.')

428

doc.add_page_break()

429

430

# Track reviewers

431

reviewer_info = {}

432

for reviewer in reviewers:

433

name, initials = reviewer.split('|')

434

reviewer_info[initials] = name

435

436

return reviewer_info

437

438

def finalize_review(doc):

439

"""Generate review summary."""

440

comments = doc.comments

441

442

# Add summary section

443

doc.add_page_break()

444

doc.add_heading('Review Summary', level=1)

445

446

if len(comments) == 0:

447

doc.add_paragraph('No comments were added during review.')

448

return

449

450

# Create summary table

451

summary_table = doc.add_table(rows=1, cols=4)

452

headers = ['#', 'Author', 'Comment', 'Status']

453

for i, header in enumerate(headers):

454

summary_table.cell(0, i).text = header

455

summary_table.cell(0, i).paragraphs[0].runs[0].bold = True

456

457

# Add comment data

458

for i, comment in enumerate(comments, 1):

459

row = summary_table.add_row()

460

row.cells[0].text = str(i)

461

row.cells[1].text = comment.author or 'Unknown'

462

row.cells[2].text = comment.text[:100] + ('...' if len(comment.text) > 100 else '')

463

row.cells[3].text = 'Open'

464

465

# Usage

466

reviewers = ['John Doe|JD', 'Jane Smith|JS', 'Bob Wilson|BW']

467

reviewer_info = setup_document_review(doc, reviewers)

468

469

# ... document review process ...

470

471

finalize_review(doc)

472

```