### Quick Start Installation Source: https://github.com/aidotnet/opencowork/blob/main/README.md Instructions to clone the repository, install dependencies, and run the development server. ```bash git clone https://github.com/AIDotNet/OpenCowork.git cd OpenCowork npm install npm run dev ``` -------------------------------- ### Usage Example: Recommended Method (python-docx) Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/docx/CHANGELOG.md Bash commands to install dependencies and run the simple and full example scripts for adding comments using python-docx. ```bash # Install dependencies pip install python-docx # Use the simple script python scripts/add_comment_simple.py input.docx output.docx # Use the full example python scripts/examples/add_comments_pythondocx.py document.docx reviewed.docx ``` -------------------------------- ### Headers/Footers & Page Setup Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/docx/docx-js.md Example of configuring document sections with custom page margins, orientation, page numbers, default headers, and footers. ```javascript const doc = new Document({ sections: [ { properties: { page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 }, // 1440 = 1 inch size: { orientation: PageOrientation.LANDSCAPE }, pageNumbers: { start: 1, formatType: 'decimal' } // "upperRoman", "lowerRoman", "upperLetter", "lowerLetter" } }, headers: { default: new Header({ children: [ new Paragraph({ alignment: AlignmentType.RIGHT, children: [new TextRun('Header Text')] }) ] }) }, footers: { default: new Footer({ children: [ new Paragraph({ alignment: AlignmentType.CENTER, children: [ new TextRun('Page '), new TextRun({ children: [PageNumber.CURRENT] }), new TextRun(' of '), new TextRun({ children: [PageNumber.TOTAL_PAGES] }) ] }) ] }) }, children: [ /* content */ ] } ] }) ``` -------------------------------- ### Complete TOC Implementation Example Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md A comprehensive Python example demonstrating how to implement an auto-generated Table of Contents using ReportLab's `TableOfContents` and a custom `TocDocTemplate`. ```python from reportlab.lib.pagesizes import letter from reportlab.platypus import SimpleDocTemplate, Paragraph, PageBreak, Spacer from reportlab.platypus.tableofcontents import TableOfContents from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import inch class TocDocTemplate(SimpleDocTemplate): def __init__(self, *args, **kwargs): SimpleDocTemplate.__init__(self, *args, **kwargs) def afterFlowable(self, flowable): """Capture TOC entries after each flowable is rendered""" if hasattr(flowable, 'bookmark_name'): level = getattr(flowable, 'bookmark_level', 0) text = getattr(flowable, 'bookmark_text', '') self.notify('TOCEntry', (level, text, self.page)) # Create document doc = TocDocTemplate("document.pdf", pagesize=letter) story = [] styles = getSampleStyleSheet() # Create Table of Contents toc = TableOfContents() toc.levelStyles = [ ParagraphStyle(name='TOCHeading1', fontSize=14, leftIndent=20, fontName='Times New Roman'), ParagraphStyle(name='TOCHeading2', fontSize=12, leftIndent=40, fontName='Times New Roman'), ] story.append(Paragraph("Table of Contents", styles['Title'])) story.append(Spacer(1, 0.2*inch)) story.append(toc) story.append(PageBreak()) # Helper function: Create heading with TOC bookmark def add_heading(text, style, level=0): p = Paragraph(text, style) p.bookmark_name = text p.bookmark_level = level p.bookmark_text = text return p # Chapter 1: Introduction story.append(add_heading("Chapter 1: Introduction", styles['Heading1'], 0)) story.append(Paragraph("This is the introduction chapter with some example content.", styles['Normal'])) story.append(Spacer(1, 0.2*inch)) story.append(add_heading("1.1 Background", styles['Heading2'], 1)) story.append(Paragraph("Background information goes here.", styles['Normal'])) # Chapter 2: Conclusion story.append(add_heading("Chapter 2: Conclusion", styles['Heading1'], 0)) story.append(Paragraph("This concludes our document.", styles['Normal'])) story.append(Spacer(1, 0.2*inch)) story.append(add_heading("2.1 Summary", styles['Heading2'], 1)) story.append(Paragraph("Summary of the document.", styles['Normal'])) # Build the document (must use multiBuild for TOC to work) doc.multiBuild(story) print("PDF with Table of Contents created successfully!") ``` -------------------------------- ### Complete Table Example with Styles Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Provides a comprehensive example of creating a table using ReportLab, including defining various ParagraphStyles for headers and cells with different alignments, and importing necessary components. ```python from reportlab.platypus import Table, TableStyle, Paragraph, Image from reportlab.lib.styles import ParagraphStyle from reportlab.lib import colors from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT, TA_JUSTIFY # Define styles for table cells header_style = ParagraphStyle( name='TableHeader', fontName='Times New Roman', fontSize=11, textColor=colors.white, alignment=TA_CENTER ) cell_style = ParagraphStyle( name='TableCell', fontName='Times New Roman', fontSize=10, textColor=colors.black, alignment=TA_CENTER ) cell_style_jus = ParagraphStyle( name='TableCellLeft', fontName='Times New Roman', fontSize=10, textColor=colors.black, alignment=TA_JUSTIFY ) cell_style_right = ParagraphStyle( name='TableCellRight', fontName='Times New Roman', fontSize=10, textColor=colors.black, alignment=TA_RIGHT ) ``` -------------------------------- ### Cover Page Style Example Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Python code example demonstrating cover page styling with specific font sizes, spacing, and alignment. ```python story.append(Paragraph( 'RoutinAI Copilot (RoutinAI 协作助手) is built by routin.ai' 'My name is RoutinAI Analyst (洞察顾问)', enbody_style )) cnbody_style = ParagraphStyle( name="CNBodyStyle", fontName="SimHei", # Base font for Chinese fontSize=10.5, leading=18, alignment=TA_JUSTIFY, ) # Wrap Chinese segments with tag story.append(Paragraph( '本报告使用 GPT-4 ' '和 GLM 进行测试。', cnbody_style )) ``` -------------------------------- ### Font Rules Example Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Example of registering fonts and applying them to paragraphs with mixed languages. ```python from reportlab.lib.styles import ParagraphStyle from reportlab.platypus import Paragraph from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont pdfmetrics.registerFont(TTFont('SimHei', '/usr/share/fonts/truetype/chinese/SimHei.ttf')) pdfmetrics.registerFont(TTFont('Times New Roman', '/usr/share/fonts/truetype/english/Times-New-Roman.ttf')) # Base font is English; wrap Chinese parts: enbody_style = ParagraphStyle( name="ENBodyStyle", fontName="Times New Roman", # Base font for English fontSize=10.5, leading=18, alignment=TA_JUSTIFY, ) # Wrap Chinese segments with tag story.append(Paragraph( 'RoutinAI Copilot (RoutinAI 协作助手) is built by routin.ai' 'My name is RoutinAI Analyst (洞察顾问)', '企业智能文档 services are powered by routin.ai.', enbody_style )) ``` -------------------------------- ### Simple tweet example Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/post-to-x/SKILL.md An example of posting a simple tweet. ```bash # Simple tweet python scripts/post_to_x.py "Hello X! 👋" ``` -------------------------------- ### Creating a Table with Styled Data Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Example demonstrating how to create a table with styled text, including bolding, superscripts, and subscripts, using the reportlab library. ```python data = [ # Header row - bold text with Paragraph [ Paragraph('Parameter', header_style), Paragraph('Unit', header_style), Paragraph('Value', header_style), Paragraph('Note', header_style) ], # Data rows - all text in Paragraph [ Paragraph('Temperature', cell_style_jus), Paragraph('°C', cell_style), Paragraph('25.5', cell_style_jus), Paragraph('Ambient', cell_style) ], [ Paragraph('Pressure', cell_style_jus), Paragraph('Pa', cell_style), Paragraph('1.01 × 105', cell_style_jus), # Scientific notation Paragraph('Standard', cell_style) ], [ Paragraph('Density', cell_style_jus), Paragraph('kg/m3', cell_style), # Unit with exponent Paragraph('1.225', cell_style_jus), Paragraph('Air at STP', cell_style) ], [ Paragraph('H2O Content', cell_style_jus), # Subscript Paragraph('%', cell_style), Paragraph('45.2', cell_style_jus), Paragraph('Relative humidity', cell_style) ] ] # Create table table = Table(data, colWidths=[120, 80, 100, 120]) table.setStyle(TableStyle([ # Header styling ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#1F4E79')), ('TEXTCOLOR', (0, 0), (-1, 0), colors.white), # Alternating row colors ('BACKGROUND', (0, 1), (-1, 1), colors.white), ('BACKGROUND', (0, 2), (-1, 2), colors.HexColor('#F5F5F5')), ('BACKGROUND', (0, 3), (-1, 3), colors.white), ('BACKGROUND', (0, 4), (-1, 4), colors.HexColor('#F5F5F5')), # Grid and alignment ('GRID', (0, 0), (-1, -1), 0.5, colors.grey), ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'), ('LEFTPADDING', (0, 0), (-1, -1), 8), ('RIGHTPADDING', (0, 0), (-1, -1), 8), ('TOPPADDING', (0, 0), (-1, -1), 6), ('BOTTOMPADDING', (0, 0), (-1, -1), 6), ])) ``` -------------------------------- ### Complete Python Example for Character Handling Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Demonstrates how to register fonts, define paragraph styles, and use Paragraph objects with tags for bold text, scientific notation with superscripts, and chemical formulas with subscripts. ```python # --- Register fonts and font family --- pdfmetrics.registerFont(TTFont('Times New Roman', '/usr/share/fonts/truetype/english/Times-New-Roman.ttf')) # CRITICAL: Must call registerFontFamily() to enable and tags registerFontFamily('Times New Roman', normal='Times New Roman', bold='Times New Roman') # --- Define styles --- body_style = ParagraphStyle( name='BodyStyle', fontName='Times New Roman', fontSize=10, textColor=colors.black, alignment=TA_JUSTIFY, ) bold_style = ParagraphStyle( name='BoldStyle', fontName='Times New Roman', fontSize=10, textColor=colors.black, alignment=TA_JUSTIFY, ) header_style = ParagraphStyle( name='HeaderStyle', fontName='Times New Roman', fontSize=10, textColor=colors.white, alignment=TA_JUSTIFY, ) # --- Body text examples --- # Bold title title = Paragraph('Scientific Formulas and Chemical Expressions', bold_style) # Math formula with superscript and mathematical symbol × math_text = Paragraph( 'The Einstein mass-energy equivalence is expressed as E = mc2. ' 'In applied physics, the gravitational force is F = 6.674 × 10-11 × ' 'm1m2/r2, ' 'and the quadratic formula solves a2 + b2 = c2.', body_style, ) # Chemical expressions with subscript chem_text = Paragraph( 'The combustion of methane: CH4 + 2O2 ' '= CO2 + 2H2O. ' 'Sulfuric acid (H2SO4) reacts with sodium hydroxide to produce ' 'Na2SO4 and water.', body_style, ) ``` -------------------------------- ### Dependencies - LibreOffice installation Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/docx/SKILL.md Install LibreOffice using apt-get. ```bash sudo apt-get install libreoffice ``` -------------------------------- ### Multi-line tweet example Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/post-to-x/SKILL.md An example of posting a multi-line tweet with hashtags. ```bash # Multi-line tweet python scripts/post_to_x.py "🚀 New product launch!\n\n✨ Feature 1: xxx\n✨ Feature 2: yyy\n\n#ProductLaunch #NewFeature" ``` -------------------------------- ### Basic PDF Creation Example Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md A simple Python script using reportlab to create a PDF file, add text, draw a line, and save the document. ```python from reportlab.lib.pagesizes import letter from reportlab.pdfgen import canvas c = canvas.Canvas("hello.pdf", pagesize=letter) width, height = letter # Add text c.drawString(100, height - 100, "Hello World!") c.drawString(100, height - 120, "This is a PDF created with reportlab") # Add a line c.line(100, height - 140, 400, height - 140) # Save c.save() ``` -------------------------------- ### Dependencies - pandoc installation Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/docx/SKILL.md Install pandoc using apt-get. ```bash sudo apt-get install pandoc ``` -------------------------------- ### ReportLab Paragraph Examples Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Demonstrates how to use ReportLab's Paragraph object with tags for superscripts, subscripts, bold text, and mathematical operators, along with setting up paragraph styles. ```python from reportlab.platypus import Paragraph from reportlab.lib.styles import ParagraphStyle from reportlab.lib.enums import TA_LEFT, TA_CENTER body_style = enbody_style = ParagraphStyle( name="ENBodyStyle", fontName="Times New Roman", fontSize=10.5, leading=18, alignment=TA_JUSTIFY, ) header_style = ParagraphStyle( name='CoverTitle', fontName='Times New Roman', fontSize=42, leading=50, alignment=TA_CENTER, spaceAfter=36 ) # Superscript: area unit Paragraph('Total area: 500 m2', body_style) # Subscript: chemical formula Paragraph('The reaction produces CO2 and H2O', body_style) # Scientific notation: large number with superscript Paragraph('Speed of light: 3.0 × 108 m/s', body_style) # Combined superscript and subscript Paragraph('Ek = mv2/2', body_style) # Bold heading Paragraph('Chapter 1: Introduction', header_style) # Math symbols in body text Paragraph('When ∠ A = 90°, AB ⊥ AC and ΔABC ≅ ΔDEF', body_style) ``` -------------------------------- ### Dependencies - docx installation Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/docx/SKILL.md Install the 'docx' package using bun. ```bash bun add docx ``` -------------------------------- ### Fetch a Web Page (Static) - Example 1 Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/web-scraper/SKILL.md Example of fetching an article from a given URL. ```bash # Fetch an article python fetch_page.py "https://example.com/article" ``` -------------------------------- ### Fetch a Web Page (Static) - Example 3 Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/web-scraper/SKILL.md Example of fetching raw full-page Markdown with a character limit. ```bash # Fetch raw full-page markdown, limit to 5000 chars python fetch_page.py "https://example.com" --raw --max-length 5000 ``` -------------------------------- ### Example: Cold outreach Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/email-drafter/SKILL.md Example of generating a cold outreach email and saving it to a file. ```bash # Cold outreach python scripts/email_draft.py --type cold-outreach --to "Sarah" --from "Alex" --subject "Partnership opportunity" --body "mutual benefit;our platform capabilities;propose a call" --tone professional --save outreach.txt ``` -------------------------------- ### Dependencies - Poppler installation Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/docx/SKILL.md Install Poppler utilities (including pdftoppm) using apt-get. ```bash sudo apt-get install poppler-utils ``` -------------------------------- ### Palette and Application Example Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/xlsx/SKILL.md Shows the color palette constraints and an example of applying styles to data headers and titles using openpyxl. ```python # Palette from openpyxl.styles import Alignment, Border, Font, Side, PatternFill, # Base & Accents background_white = "FFFFFF" # background background_row_alt = "E9E9E9" # Alternating row fill grey_header = "333333" # Section headers border_grey = "E3DEDE" # Standard borders blue_primary = "0B5CAD" # Primary Accent # Application Example: Data Headers (NOT Titles) header_fill = PatternFill(start_color=grey_header, end_color=grey_header, fill_type="solid") header_font = Font(name='Times New Roman', color="FFFFFF", bold=True) for cell in sheet['B3:E3'][0]: cell.fill = header_fill cell.font = header_font # Example: Title style (NO shading, left-aligned) title_font = Font(name='Times New Roman', size=18, bold=True, color="000000") title_alignment = Alignment(horizontal='left', vertical='center') sheet['B2'].font = title_font sheet['B2'].alignment = title_alignment # NO fill for titles ``` -------------------------------- ### Install Dependencies (Lightweight) Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/web-scraper/SKILL.md Installs dependencies for lightweight scraping of static pages, search, and link extraction. ```bash pip install requests beautifulsoup4 readability-lxml html2text ddgs ``` -------------------------------- ### Search the Web - Example 1 Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/web-scraper/SKILL.md Example of a general web search query. ```bash # General search python search_web.py "Python web scraping best practices 2025" ``` -------------------------------- ### Example MCP Server Configuration Source: https://github.com/aidotnet/opencowork/blob/main/docs/docs/capabilities/mcp-servers.mdx An example JSON configuration for an MCP server, specifically for integrating with GitHub. ```json { "id": "github", "name": "GitHub MCP", "enabled": true, "transport": "stdio", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "..." } } ``` -------------------------------- ### Fetch a Web Page (Static) - Example 2 Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/web-scraper/SKILL.md Example of extracting only table elements from a URL. ```bash # Extract only tables python fetch_page.py "https://example.com/data" --selector "table" ``` -------------------------------- ### Setup and Initialization Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/docx/docx-js.md Imports necessary components from the 'docx' library and demonstrates basic document creation and saving for both Node.js and browser environments. ```javascript const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun, Media, Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink, InternalHyperlink, TableOfContents, HeadingLevel, BorderStyle, WidthType, TabStopType, TabStopPosition, UnderlineType, ShadingType, VerticalAlign, SymbolRun, PageNumber, FootnoteReferenceRun, Footnote, PageBreak } = require('docx') // Create & Save const doc = new Document({ sections: [ { children: [ /* content */ ] } ] }) Packer.toBuffer(doc).then((buffer) => fs.writeFileSync('doc.docx', buffer)) // Node.js Packer.toBlob(doc).then((blob) => { /* download logic */ }) // Browser ``` -------------------------------- ### Install Dependencies Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/excel-processor/SKILL.md Installs the necessary openpyxl library for Excel processing. This is a one-time setup. ```bash pip install openpyxl ``` -------------------------------- ### Prerequisites Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/post-to-x/SKILL.md Installs Playwright and downloads the Chromium browser. ```bash pip install playwright playwright install chromium ``` -------------------------------- ### Docs Site Build Commands Source: https://github.com/aidotnet/opencowork/blob/main/docs/docs/reference/building.mdx Commands for installing dependencies, running the development server, and building the documentation site for production. ```bash cd docs npm install npm run dev # Local development npm run build # Production build (output: standalone) ``` -------------------------------- ### PROHIBIT - Manual TOC Entry Example Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md An example of how NOT to create TOC entries, demonstrating manual creation of entries with hardcoded page numbers and leader dots. ```python toc_entries = [("1. Title", "5"), ("2. Section", "10")] for entry, page in toc_entries: story.append(Paragraph(f"{entry} {'.'*50} {page}", style)) ``` -------------------------------- ### Basic List Syntax with Numbering Configuration Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/docx/docx-js.md Provides an example of setting up numbering configurations for bullet lists and numbered lists, and then creating paragraphs that utilize these configurations. It highlights the importance of using `LevelFormat.BULLET` and different references for independent lists. ```javascript // Bullets - ALWAYS use the numbering config, NOT unicode symbols // CRITICAL: Use LevelFormat.BULLET constant, NOT the string "bullet" const doc = new Document({ numbering: { config: [ { reference: 'bullet-list', levels: [ { level: 0, format: LevelFormat.BULLET, text: '•', alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 720, hanging: 360 } } } } ] }, { reference: 'first-numbered-list', levels: [ { level: 0, format: LevelFormat.DECIMAL, text: '%1.', alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 720, hanging: 360 } } } } ] }, { reference: 'second-numbered-list', // Different reference = restarts at 1 levels: [ { level: 0, format: LevelFormat.DECIMAL, text: '%1.', alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 720, hanging: 360 } } } } ] } ] }, sections: [ { children: [ // Bullet list items new Paragraph({ numbering: { reference: 'bullet-list', level: 0 }, children: [new TextRun('First bullet point')] }), new Paragraph({ numbering: { reference: 'bullet-list', level: 0 }, children: [new TextRun('Second bullet point')] }), // Numbered list items new Paragraph({ numbering: { reference: 'first-numbered-list', level: 0 }, children: [new TextRun('First numbered item')] }), new Paragraph({ numbering: { reference: 'first-numbered-list', level: 0 }, children: [new TextRun('Second numbered item')] }), // ⚠️ CRITICAL: Different reference = INDEPENDENT list that restarts at 1 // Same reference = CONTINUES previous numbering new Paragraph({ numbering: { reference: 'second-numbered-list', level: 0 }, children: [new TextRun('Starts at 1 again (because different reference)')] }) ] } ] }) // ⚠️ CRITICAL: NEVER use unicode bullets - they create fake lists that don't work properly // new TextRun("• Item") // WRONG // new SymbolRun({ char: "2022" }) // WRONG // ✅ ALWAYS use numbering config with LevelFormat.BULLET for real Word lists ``` -------------------------------- ### Table Styling Example Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/docx/docx-js.md Demonstrates creating a centered table with specific cell styling, including vertical alignment, shading, and borders. ```javascript new Table({ alignment: AlignmentType.CENTER, rows: [ new TableRow({ children: [ new TableCell({ children: [ new Paragraph({ text: 'centered text', alignment: AlignmentType.CENTER }) ], verticalAlign: VerticalAlign.CENTER, shading: { fill: colors.tableBg }, borders: cellBorders }) ] }) ] }) ``` -------------------------------- ### Show help Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Display help information for the add_routinai_metadata.py script. ```bash # Show help python scripts/add_routinai_metadata.py --help ``` -------------------------------- ### Set/Update Metadata (RoutinAI Branding) Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Command-line examples for adding RoutinAI branding metadata to PDFs. ```bash # Add metadata to a single PDF (in-place) python scripts/add_routinai_metadata.py document.pdf # Add metadata with custom title python scripts/add_routinai_metadata.py report.pdf -t "Q4 Financial Analysis" # Batch process multiple PDFs python scripts/add_routinai_metadata.py *.pdf ``` -------------------------------- ### Read a PDF and Extract Text Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Example of reading a PDF and extracting all its text content using pypdf. ```python from pypdf import PdfReader, PdfWriter # Read a PDF reader = PdfReader("document.pdf") print(f"Pages: {len(reader.pages)}") # Extract text text = "" for page in reader.pages: text += page.extract_text() ``` -------------------------------- ### Wrap Chinese segments with tag Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Example of appending paragraphs with Chinese segments wrapped in a tag for specific font rendering. ```python story.append(Paragraph( 'RoutinAI Copilot (RoutinAI 协作助手) is built by routin.ai' 'My name is RoutinAI Analyst (洞察顾问)', '企业智能文档 services are powered by routin.ai.' enbody_style )) ``` -------------------------------- ### Registering a Viewer Source: https://github.com/aidotnet/opencowork/blob/main/docs/docs/capabilities/file-preview.mdx Example of how to register a new viewer for specific file extensions. ```typescript viewerRegistry.register({ type: 'markdown', extensions: ['.md', '.mdx'], component: MarkdownViewer }) ``` -------------------------------- ### Table Cell Content Formatting (Prohibited Example) Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Illustrates a prohibited way of adding plain strings to table cells, which will not render formatting tags. ```python # NEVER DO THIS - formatting will NOT work data = [ ['Header', 'Value'], # Bold won't render ['Temperature', '25°C'], # No style control ['Pressure', '1.01 × 105'], # Superscript won't work ] ``` -------------------------------- ### Usage Example: Advanced Method (OOXML) Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/docx/CHANGELOG.md Bash commands demonstrating the workflow for the OOXML method, involving unpacking, adding comments, and repacking the document. ```bash # Unpack, process, and pack python ooxml/scripts/unpack.py document.docx unpacked python scripts/add_comment.py unpacked 10 "批注内容" python ooxml/scripts/pack.py unpacked output.docx ``` -------------------------------- ### Chinese and English Text Formatting Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Example of setting a base font for Chinese and wrapping English segments with a font tag within a Paragraph object. ```python cnbody_style = ParagraphStyle( name="CNBodyStyle", fontName="SimHei", # Base font for Chinese fontSize=10.5, leading=18, alignment=TA_JUSTIFY, ) # Wrap Chinese segments with tag story.append(Paragraph( '本报告使用 GPT-4 ' '和 GLM 进行测试。', cnbody_style )) ``` -------------------------------- ### 更新文档 Source: https://github.com/aidotnet/opencowork/blob/main/docs/docs/reference/contributing.mdx Commands to run the documentation development server. ```bash cd docs npm run dev ``` -------------------------------- ### Base font is Chinese; wrap English parts Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Example of setting a base Chinese font and wrapping English segments with a specific font tag. ```python cnbody_style = ParagraphStyle( name="CNBodyStyle", fontName="SimHei", # Base font for Chinese fontSize=10.5, leading=18, alignment=TA_JUSTIFY, ) # Wrap Chinese segments with tag story.append(Paragraph( '本报告使用 GPT-4 ' '和 GLM 进行测试。', cnbody_style )) ``` -------------------------------- ### Create PDF Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Basic PDF creation step before adding metadata. ```python doc.build(story) print("PDF built") ``` -------------------------------- ### Build Commands Source: https://github.com/aidotnet/opencowork/blob/main/docs/docs/reference/building.mdx Commands for type checking, building the production version, and packaging for different platforms. ```bash # Type checking + build (recommended) npm run build # Build platform-specific installers npm run build:win # Windows (.exe) npm run build:mac # macOS (.dmg) npm run build:linux # Linux (.AppImage / .deb) ``` -------------------------------- ### Preventing Unwanted Line Breaks - Non-breaking Space Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Example showing how to use a non-breaking space (U+00A0) to prevent English names from breaking at awkward positions. ```python # PROHIBITED: "K.G. Palepu" may break after "K.G." text = Paragraph("Professors (K.G. Palepu) proposed...",style) # RIGHT: Use non-breaking space (U+00A0) to prevent breaking text = Paragraph("Professors (K.G.\u00A0Palepu) proposed...",style) ``` -------------------------------- ### Table Cell Content Formatting (Required Example) Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Demonstrates the mandatory way to wrap all text content in table cells with Paragraph() objects to ensure proper formatting. ```python # ALWAYS DO THIS data = [ [Paragraph('Header', header_style), Paragraph('Value', header_style)], [Paragraph('Temperature', cell_style), Paragraph('25°C', cell_style)], [Paragraph('Pressure', cell_style), Paragraph('1.01 × 105', cell_style)], ] ``` -------------------------------- ### Preventing Unwanted Line Breaks - Word Wrap for Punctuation Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Example demonstrating the use of 'wordWrap="CJK"' in ParagraphStyle to handle punctuation at the beginning of a line correctly. ```python # RIGHT: Add wordWrap='CJK' for proper typography styles.add(ParagraphStyle( name='BodyStyle', fontName='SimHei', fontSize=10.5, leading=18, alignment=TA_LEFT, wordWrap='CJK' # Prevents orphaned punctuation )) ``` -------------------------------- ### Custom Styles Example Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/docx/docx-js.md Example of defining custom styles for a Word document, including font size, bolding, font family, and paragraph spacing. ```javascript styles.create({ paragraphStyles: [ { id: 'Heading1', name: 'Heading 1', basedOn: 'Normal', next: 'Normal', quickFormat: true, run: { size: 32, bold: true, font: 'SimSun' }, // SimSun 16pt for H1 paragraph: { spacing: { before: 240, after: 240 }, outlineLevel: 0 } }, { id: 'Heading2', name: 'Heading 2', basedOn: 'Normal', next: 'Normal', quickFormat: true, run: { size: 28, bold: true, font: 'SimHei' }, // SimHei 14pt for H2 paragraph: { spacing: { before: 180, after: 180 }, outlineLevel: 1 } } ] }) ``` -------------------------------- ### Development Commands Source: https://github.com/aidotnet/opencowork/blob/main/docs/AGENTS.md Common commands for development, building, and testing the project. ```bash npm install npm run dev npm run types:check npm run build npm run start docker compose up --build ``` -------------------------------- ### Creating New PDFs with Metadata Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Example using reportlab to create a new PDF document and set essential metadata fields like Title, Author, Creator, Subject, and Description. ```python from reportlab.lib.pagesizes import letter from reportlab.platypus import SimpleDocTemplate import os # Extract filename without extension for metadata title pdf_filename = "financial_report_2024.pdf" title_for_metadata = os.path.splitext(pdf_filename)[0] # "financial_report_2024" doc = SimpleDocTemplate( pdf_filename, pagesize=letter, title=title_for_metadata, # MUST: Match filename author='RoutinAI', # MUST: Set to "RoutinAI" creator='RoutinAI', # MUST: Set to "RoutinAI" subject='Annual financial analysis and performance metrics' # SHOULD: Describe purpose ) ``` -------------------------------- ### Modifying Existing PDFs with Metadata Source: https://github.com/aidotnet/opencowork/blob/main/resources/skills/pdf/SKILL.md Example using pypdf to read an existing PDF, add pages to a writer object, and set required metadata fields (Title, Author, Creator, Subject). ```python from pypdf import PdfReader, PdfWriter import os pdf_filename = "output.pdf" title_for_metadata = os.path.splitext(os.path.basename(pdf_filename))[0] reader = PdfReader("input.pdf") writer = PdfWriter() for page in reader.pages: writer.add_page(page) # Set metadata: Title, Author, Creator are REQUIRED writer.add_metadata({ '/Title': title_for_metadata, # MUST: Match filename '/Author': 'RoutinAI', # MUST: Set to "RoutinAI" '/Subject': 'Document purpose description', # SHOULD: Describe purpose '/Creator': 'RoutinAI' # MUST: Set to "RoutinAI" }) with open(pdf_filename, "wb") as output: writer.write(output) ```