office-design-toolkit

"Bộ kỹ năng Office (DOCX/PPTX/XLSX/PDF) và Design Toolkit tích hợp từ file người dùng cung cấp."

0xAstroAlpha
by 0xAstroAlpha
Other · MIT · Updated: 5 months ago
25
stars
11
Forks
community
BBB
Safety
high
AA
Quality

name: office-design-toolkit description: "Bộ kỹ năng Office (DOCX/PPTX/XLSX/PDF) và Design Toolkit tích hợp từ file người dùng cung cấp."

📂 OFFICE FILE SKILLS & DESIGN DOCUMENT TOOLKIT

Tổng hợp toàn bộ Skills xử lý file Office + Design chuyên nghiệp


PHẦN 1: DOCX — Word Document Skill

Path: /mnt/skills/public/docx/SKILL.md

Overview

File .docx là ZIP archive chứa XML files.

Quick Reference

Task Approach
Read/analyze content pandoc hoặc unpack raw XML
Create new document Dùng docx-js
Edit existing document Unpack → edit XML → repack

Converting .doc to .docx

python scripts/office/soffice.py --headless --convert-to docx document.doc

Reading Content

pandoc --track-changes=all document.docx -o output.md
python scripts/office/unpack.py document.docx unpacked/

Converting to Images

python scripts/office/soffice.py --headless --convert-to pdf document.docx
pdftoppm -jpeg -r 150 document.pdf page

Accepting Tracked Changes

python scripts/accept_changes.py input.docx output.docx

Creating New Documents (docx-js)

Setup

const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun,
        Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink,
        InternalHyperlink, Bookmark, FootnoteReferenceRun, PositionalTab,
        PositionalTabAlignment, PositionalTabRelativeTo, PositionalTabLeader,
        TabStopType, TabStopPosition, Column, SectionType,
        TableOfContents, HeadingLevel, BorderStyle, WidthType, ShadingType,
        VerticalAlign, PageNumber, PageBreak } = require('docx');

const doc = new Document({ sections: [{ children: [/* content */] }] });
Packer.toBuffer(doc).then(buffer => fs.writeFileSync("doc.docx", buffer));

Validation

python scripts/office/validate.py doc.docx

Page Size

// CRITICAL: docx-js defaults to A4, not US Letter
sections: [{
  properties: {
    page: {
      size: { width: 12240, height: 15840 },  // US Letter in DXA
      margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 }
    }
  },
  children: [/* content */]
}]

Common page sizes (DXA units, 1440 DXA = 1 inch):

Paper Width Height Content Width (1" margins)
US Letter 12,240 15,840 9,360
A4 (default) 11,906 16,838 9,026

Landscape: Pass portrait dimensions, let docx-js swap:

size: {
  width: 12240,   // SHORT edge
  height: 15840,  // LONG edge
  orientation: PageOrientation.LANDSCAPE
},

Styles (Override Built-in Headings)

const doc = new Document({
  styles: {
    default: { document: { run: { font: "Arial", size: 24 } } },
    paragraphStyles: [
      { id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal", quickFormat: true,
        run: { size: 32, bold: true, font: "Arial" },
        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: "Arial" },
        paragraph: { spacing: { before: 180, after: 180 }, outlineLevel: 1 } },
    ]
  },
  sections: [{
    children: [
      new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun("Title")] }),
    ]
  }]
});

Lists (NEVER use unicode bullets)

// ❌ WRONG
new Paragraph({ children: [new TextRun("• Item")] })

// ✅ CORRECT
const doc = new Document({
  numbering: {
    config: [
      { reference: "bullets",
        levels: [{ level: 0, format: LevelFormat.BULLET, text: "•", alignment: AlignmentType.LEFT,
          style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
      { reference: "numbers",
        levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT,
          style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
    ]
  },
  sections: [{
    children: [
      new Paragraph({ numbering: { reference: "bullets", level: 0 },
        children: [new TextRun("Bullet item")] }),
    ]
  }]
});

Tables

// CRITICAL: Tables need dual widths - columnWidths on table AND width on each cell
const border = { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" };
const borders = { top: border, bottom: border, left: border, right: border };

new Table({
  width: { size: 9360, type: WidthType.DXA },
  columnWidths: [4680, 4680],
  rows: [
    new TableRow({
      children: [
        new TableCell({
          borders,
          width: { size: 4680, type: WidthType.DXA },
          shading: { fill: "D5E8F0", type: ShadingType.CLEAR },
          margins: { top: 80, bottom: 80, left: 120, right: 120 },
          children: [new Paragraph({ children: [new TextRun("Cell")] })]
        })
      ]
    })
  ]
})

Images

new Paragraph({
  children: [new ImageRun({
    type: "png",
    data: fs.readFileSync("image.png"),
    transformation: { width: 200, height: 150 },
    altText: { title: "Title", description: "Desc", name: "Name" }
  })]
})

Page Breaks

new Paragraph({ children: [new PageBreak()] })
new Paragraph({ pageBreakBefore: true, children: [new TextRun("New page")] })

Hyperlinks

// External
new Paragraph({
  children: [new ExternalHyperlink({
    children: [new TextRun({ text: "Click here", style: "Hyperlink" })],
    link: "https://example.com",
  })]
})

// Internal (bookmark + reference)
new Paragraph({ heading: HeadingLevel.HEADING_1, children: [
  new Bookmark({ id: "chapter1", children: [new TextRun("Chapter 1")] }),
]})
new Paragraph({ children: [new InternalHyperlink({
  children: [new TextRun({ text: "See Chapter 1", style: "Hyperlink" })],
  anchor: "chapter1",
})]})

Footnotes

const doc = new Document({
  footnotes: {
    1: { children: [new Paragraph("Source: Annual Report 2024")] },
  },
  sections: [{
    children: [new Paragraph({
      children: [
        new TextRun("Revenue grew 15%"),
        new FootnoteReferenceRun(1),
      ],
    })]
  }]
});

Tab Stops

new Paragraph({
  children: [
    new TextRun("Company Name"),
    new TextRun("\tJanuary 2025"),
  ],
  tabStops: [{ type: TabStopType.RIGHT, position: TabStopPosition.MAX }],
})

Multi-Column Layouts

sections: [{
  properties: {
    column: { count: 2, space: 720, equalWidth: true, separate: true },
  },
  children: [/* content flows naturally */]
}]

Table of Contents

new TableOfContents("Table of Contents", { hyperlink: true, headingStyleRange: "1-3" })

Headers/Footers

sections: [{
  properties: {
    page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } }
  },
  headers: {
    default: new Header({ children: [new Paragraph({ children: [new TextRun("Header")] })] })
  },
  footers: {
    default: new Footer({ children: [new Paragraph({
      children: [new TextRun("Page "), new TextRun({ children: [PageNumber.CURRENT] })]
    })] })
  },
  children: [/* content */]
}]

Critical Rules for docx-js

Editing Existing Documents

Step 1: Unpack

python scripts/office/unpack.py document.docx unpacked/

Step 2: Edit XML

Step 3: Pack

python scripts/office/pack.py unpacked/ output.docx --original document.docx

XML Reference — Tracked Changes

<!-- Insertion -->
<w:ins w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">
  <w:r><w:t>inserted text</w:t></w:r>
</w:ins>

<!-- Deletion -->
<w:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">
  <w:r><w:delText>deleted text</w:delText></w:r>
</w:del>

Dependencies


PHẦN 2: PPTX — PowerPoint Skill

Path: /mnt/skills/public/pptx/SKILL.md

Quick Reference

Task Guide
Read/analyze content python -m markitdown presentation.pptx
Edit or create from template Xem editing workflow
Create from scratch Dùng PptxGenJS

Reading Content

python -m markitdown presentation.pptx
python scripts/thumbnail.py presentation.pptx
python scripts/office/unpack.py presentation.pptx unpacked/

Design Ideas — CRITICAL

Before Starting

Color Palettes

Theme Primary Secondary Accent
Midnight Executive 1E2761 CADCFC FFFFFF
Forest & Moss 2C5F2D 97BC62 F5F5F5
Coral Energy F96167 F9E795 2F3C7E
Warm Terracotta B85042 E7E8D1 A7BEAE
Ocean Gradient 065A82 1C7293 21295C
Charcoal Minimal 36454F F2F2F2 212121
Teal Trust 028090 00A896 02C39A
Berry & Cream 6D2E46 A26769 ECE2D0
Sage Calm 84B59F 69A297 50808E
Cherry Bold 990011 FCF6F5 2F3C7E

For Each Slide

Typography

Header Font Body Font
Georgia Calibri
Arial Black Arial
Cambria Calibri
Trebuchet MS Calibri
Palatino Garamond
Element Size
Slide title 36-44pt bold
Section header 20-24pt bold
Body text 14-16pt
Captions 10-12pt muted

Avoid (Common Mistakes)

PptxGenJS — Creating from Scratch

Setup

const pptxgen = require("pptxgenjs");
let pres = new pptxgen();
pres.layout = 'LAYOUT_16x9';

let slide = pres.addSlide();
slide.addText("Hello World!", { x: 0.5, y: 0.5, fontSize: 36, color: "363636" });
pres.writeFile({ fileName: "Presentation.pptx" });

Layout Dimensions

Text & Formatting

slide.addText("Simple Text", {
  x: 1, y: 1, w: 8, h: 2, fontSize: 24, fontFace: "Arial",
  color: "363636", bold: true, align: "center", valign: "middle"
});

// Rich text arrays
slide.addText([
  { text: "Bold ", options: { bold: true } },
  { text: "Italic ", options: { italic: true } }
], { x: 1, y: 3, w: 8, h: 1 });

// Multi-line (requires breakLine: true)
slide.addText([
  { text: "Line 1", options: { breakLine: true } },
  { text: "Line 2", options: { breakLine: true } },
  { text: "Line 3" }
], { x: 0.5, y: 0.5, w: 8, h: 2 });

Lists & Bullets

// ✅ CORRECT
slide.addText([
  { text: "First item", options: { bullet: true, breakLine: true } },
  { text: "Second item", options: { bullet: true, breakLine: true } },
  { text: "Third item", options: { bullet: true } }
], { x: 0.5, y: 0.5, w: 8, h: 3 });

// ❌ NEVER use unicode bullets

Shapes

slide.addShape(pres.shapes.RECTANGLE, {
  x: 0.5, y: 0.8, w: 1.5, h: 3.0,
  fill: { color: "FF0000" }, line: { color: "000000", width: 2 }
});

// Rounded rectangle
slide.addShape(pres.shapes.ROUNDED_RECTANGLE, {
  x: 1, y: 1, w: 3, h: 2,
  fill: { color: "FFFFFF" }, rectRadius: 0.1
});

// With shadow
slide.addShape(pres.shapes.RECTANGLE, {
  x: 1, y: 1, w: 3, h: 2,
  fill: { color: "FFFFFF" },
  shadow: { type: "outer", color: "000000", blur: 6, offset: 2, angle: 135, opacity: 0.15 }
});

Images

slide.addImage({ path: "images/chart.png", x: 1, y: 1, w: 5, h: 3 });

// With options
slide.addImage({
  path: "image.png", x: 1, y: 1, w: 5, h: 3,
  rounding: true, transparency: 50,
  sizing: { type: 'cover', w: 4, h: 3 }
});

Icons (react-icons → PNG)

const React = require("react");
const ReactDOMServer = require("react-dom/server");
const sharp = require("sharp");
const { FaCheckCircle } = require("react-icons/fa");

function renderIconSvg(IconComponent, color = "#000000", size = 256) {
  return ReactDOMServer.renderToStaticMarkup(
    React.createElement(IconComponent, { color, size: String(size) })
  );
}

async function iconToBase64Png(IconComponent, color, size = 256) {
  const svg = renderIconSvg(IconComponent, color, size);
  const pngBuffer = await sharp(Buffer.from(svg)).png().toBuffer();
  return "image/png;base64," + pngBuffer.toString("base64");
}

Charts

slide.addChart(pres.charts.BAR, [{
  name: "Sales", labels: ["Q1", "Q2", "Q3", "Q4"], values: [4500, 5500, 6200, 7100]
}], {
  x: 0.5, y: 0.6, w: 6, h: 3, barDir: 'col',
  showTitle: true, title: 'Quarterly Sales',
  chartColors: ["0D9488", "14B8A6", "5EEAD4"],
  valGridLine: { color: "E2E8F0", size: 0.5 },
  catGridLine: { style: "none" },
});

Slide Backgrounds

slide.background = { color: "F1F1F1" };
slide.background = { path: "https://example.com/bg.jpg" };
slide.background = { data: "image/png;base64,..." };

Common Pitfalls

  1. NEVER use "#" with hex colors — causes corruption
  2. NEVER encode opacity in hex string — use opacity property
  3. Use bullet: true — NEVER unicode "•"
  4. Use breakLine: true between items
  5. NEVER reuse option objects (PptxGenJS mutates them)
  6. Don't use ROUNDED_RECTANGLE with accent borders

Editing Existing Presentations

Workflow

  1. Analyze: python scripts/thumbnail.py template.pptx
  2. Plan slide mapping (USE VARIED LAYOUTS!)
  3. Unpack: python scripts/office/unpack.py template.pptx unpacked/
  4. Build: Delete/duplicate/reorder slides
  5. Edit content in XML
  6. Clean: python scripts/clean.py unpacked/
  7. Pack: python scripts/office/pack.py unpacked/ output.pptx --original template.pptx

Scripts

Script Purpose
unpack.py Extract and pretty-print
add_slide.py Duplicate slide or create from layout
clean.py Remove orphaned files
pack.py Repack with validation
thumbnail.py Visual grid of slides

QA (Required!)

# Content QA
python -m markitdown output.pptx

# Visual QA — convert to images
python scripts/office/soffice.py --headless --convert-to pdf output.pptx
pdftoppm -jpeg -r 150 output.pdf slide

Dependencies


PHẦN 3: XLSX — Excel Spreadsheet Skill

Path: /mnt/skills/public/xlsx/SKILL.md

Requirements for All Excel Files

Financial Models — Color Coding

Number Formatting

CRITICAL: Use Formulas, Not Hardcoded Values

# ❌ WRONG
total = df['Sales'].sum()
sheet['B10'] = total

# ✅ CORRECT
sheet['B10'] = '=SUM(B2:B9)'
sheet['C5'] = '=(C4-C2)/C2'
sheet['D20'] = '=AVERAGE(D2:D19)'

Common Workflow

  1. Choose tool: pandas (data) or openpyxl (formulas/formatting)
  2. Create/Load
  3. Modify
  4. Save
  5. Recalculate formulas (MANDATORY):
python scripts/recalc.py output.xlsx
  1. Verify and fix errors

Creating New Files

from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment

wb = Workbook()
sheet = wb.active
sheet['A1'] = 'Hello'
sheet['B2'] = '=SUM(A1:A10)'
sheet['A1'].font = Font(bold=True, color='FF0000')
sheet['A1'].fill = PatternFill('solid', start_color='FFFF00')
sheet.column_dimensions['A'].width = 20
wb.save('output.xlsx')

Reading & Analysis

import pandas as pd
df = pd.read_excel('file.xlsx')
all_sheets = pd.read_excel('file.xlsx', sheet_name=None)

Best Practices


PHẦN 4: PDF — PDF Processing Skill

Path: /mnt/skills/public/pdf/SKILL.md

Quick Reference

Task Best Tool
Merge PDFs pypdf
Split PDFs pypdf
Extract text pdfplumber
Extract tables pdfplumber
Create PDFs reportlab
OCR scanned pytesseract
Fill PDF forms pdf-lib or pypdf (FORMS.md)

Reading PDFs

from pypdf import PdfReader
reader = PdfReader("document.pdf")
text = ""
for page in reader.pages:
    text += page.extract_text()

Extract Tables

import pdfplumber
with pdfplumber.open("document.pdf") as pdf:
    for page in pdf.pages:
        tables = page.extract_tables()
        for table in tables:
            for row in table:
                print(row)

Merge PDFs

from pypdf import PdfWriter, PdfReader
writer = PdfWriter()
for pdf_file in ["doc1.pdf", "doc2.pdf"]:
    reader = PdfReader(pdf_file)
    for page in reader.pages:
        writer.add_page(page)
with open("merged.pdf", "wb") as output:
    writer.write(output)

Create PDFs (reportlab)

from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak
from reportlab.lib.styles import getSampleStyleSheet

doc = SimpleDocTemplate("report.pdf", pagesize=letter)
styles = getSampleStyleSheet()
story = []
story.append(Paragraph("Report Title", styles['Title']))
story.append(Spacer(1, 12))
story.append(Paragraph("Body text here.", styles['Normal']))
doc.build(story)

Subscripts/Superscripts — NEVER use Unicode

# ✅ CORRECT
chemical = Paragraph("H<sub>2</sub>O", styles['Normal'])
squared = Paragraph("x<super>2</super>", styles['Normal'])

Command-Line Tools

# Extract text
pdftotext input.pdf output.txt
pdftotext -layout input.pdf output.txt

# Merge
qpdf --empty --pages file1.pdf file2.pdf -- merged.pdf

# Split
qpdf input.pdf --pages . 1-5 -- pages1-5.pdf

# Rotate
qpdf input.pdf output.pdf --rotate=+90:1

OCR Scanned PDFs

import pytesseract
from pdf2image import convert_from_path
images = convert_from_path('scanned.pdf')
text = ""
for i, image in enumerate(images):
    text += pytesseract.image_to_string(image)

Watermark & Password

# Watermark
for page in reader.pages:
    page.merge_page(watermark)
    writer.add_page(page)

# Encrypt
writer.encrypt("userpassword", "ownerpassword")

PHẦN 5: FRONTEND DESIGN Skill

Path: /mnt/skills/public/frontend-design/SKILL.md

Design Thinking Process

  1. Purpose: What problem? Who uses it?
  2. Tone: Brutally minimal, maximalist, retro-futuristic, luxury, playful, editorial, art deco, soft/pastel, industrial...
  3. Constraints: Framework, performance, accessibility
  4. Differentiation: What's UNFORGETTABLE?

Aesthetics Guidelines

Typography

Color & Theme

Motion

Spatial Composition

Backgrounds & Visual Details

NEVER


PHẦN 6: THEME FACTORY Skill

Path: /mnt/skills/examples/theme-factory/SKILL.md

10 Pre-set Themes

1. Ocean Depths — Professional maritime

2. Sunset Boulevard — Warm vibrant

3. Forest Canopy — Earth tones

4. Modern Minimalist — Grayscale

5. Golden Hour — Autumnal

6. Arctic Frost — Winter crisp

7. Desert Rose — Sophisticated dusty

8. Tech Innovation — Bold modern

9. Botanical Garden — Organic fresh

10. Midnight Galaxy — Cosmic dramatic

Usage

  1. Show theme-showcase.pdf to user
  2. Ask for choice
  3. Read theme file from themes/ directory
  4. Apply colors + fonts consistently
  5. Can also create custom themes on-the-fly

PHẦN 7: CANVAS DESIGN Skill

Path: /mnt/skills/examples/canvas-design/SKILL.md

Two-Step Process

  1. Design Philosophy Creation (.md file)
  2. Express on Canvas (.pdf or .png file)

Design Philosophy Creation

Steps

  1. Name the movement (1-2 words): "Brutalist Joy", "Chromatic Silence"
  2. Articulate the philosophy (4-6 paragraphs): Space, color, scale, rhythm, hierarchy

Philosophy Examples

Essential Principles

Canvas Creation

Available Fonts (canvas-fonts directory)

ArsenalSC, BigShoulders, Boldonse, BricolageGrotesque, CrimsonPro, DMMono, EricaOne, GeistMono, Gloock, IBMPlexMono, IBMPlexSerif, InstrumentSans, InstrumentSerif, Italiana, JetBrainsMono, Jura, LibreBaskerville, Lora, NationalPark, NothingYouCouldDo, Outfit, PixelifySans, PoiretOne, RedHatMono, Silkscreen, SmoochSans, Tektur, WorkSans, YoungSerif


PHẦN 8: CHEAT SHEET — QUICK WORKFLOW MAP

File Type → Skill Mapping

Need Skill Install
Create .docx DOCX npm install -g docx
Edit .docx DOCX unpack/edit XML/pack
Create .pptx PPTX npm install -g pptxgenjs
Edit .pptx PPTX unpack/edit XML/pack
Create .xlsx XLSX openpyxl (Python)
Edit .xlsx XLSX openpyxl + recalc.py
Create .pdf PDF reportlab (Python)
Edit .pdf PDF pypdf / pdfplumber
Beautiful web UI Frontend Design HTML/CSS/JS/React
Apply themes Theme Factory 10 preset themes
Art/poster/visual Canvas Design reportlab + fonts

Universal Design Principles

  1. Never default to generic — pick bold, context-specific aesthetics
  2. Color dominance — one color 60-70%, accents sharp
  3. Typography matters — avoid Arial/Inter/Roboto for design work
  4. Every slide/page needs visual elements — never text-only
  5. QA is mandatory — always verify output visually
  6. Formulas over hardcodes — keep spreadsheets dynamic
  7. Validate everything — use validate.py/recalc.py scripts

DOCX Style Blueprint (learned from approved client docs)

Use this as default style system when creating professional DOCX plans/proposals unless user asks otherwise.

A) Typography & Hierarchy

B) Color Tokens

B.1) Alternate Client Style Pack (from reference docs)

Use when user asks for the same visual language as approved sample files.

C) Page Layout

D) Tables (must-follow)

E) Notes & Meta Text

F) QA Checklist before delivery

Execution Standard (Sprint Rollout: Active)

Use the following references for every Office task:

Mandatory operating mode:

  1. Create/confirm content first.
  2. Build structure second.
  3. Apply design third.
  4. Run QA before delivery.

If user asks for speed, still preserve the phase order with reduced depth.

Sprint Implementation Status

Definition of done for Office output:

Brand handling:

🔓 Sign in to unlock more
Sign in with GitHub