Initial commit

This commit is contained in:
Z User
2026-06-06 05:21:10 +00:00
Unverified
commit 6664758a6d
493 changed files with 135653 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
{
"permissions": {
"allow": [
"WebFetch(domain:www.npmjs.com)",
"WebSearch",
"Bash(node -e \"const pptx = require\\('pptxgenjs'\\); console.log\\(Object.keys\\(pptx.prototype || pptx\\).slice\\(0,5\\)\\); const p = new pptx\\(\\); console.log\\(p.presLayout\\); console.log\\(typeof p.ShapeType\\);\")",
"Bash(node:*)",
"Bash(python3:*)",
"Bash(ls /share/hc/utils/superz/test_beam6/ppt_normal_zh_66/download/ppt-workspace/*.html)",
"Bash(sort -t_ -k4 -n)",
"Bash(ls /share/hc/utils/superz/test_beam6/ppt_normal_zh_79/download/ppt-workspace/*.html)",
"Bash(ls /share/hc/utils/superz/test_beam6/ppt_normal_zh_78/download/ppt-workspace/*.html)",
"Bash(xargs -I{} head -3 {})",
"Bash(npm root:*)",
"Read(//root/.nvm/versions/node/v24.14.1/lib/node_modules/**)",
"Read(//usr/**)",
"Bash(NODE_PATH=/share/hc/utils/superz/p-p-p-x/ppt0403/node_modules node:*)"
]
}
}

13
skills/ppt/LICENSE.txt Executable file
View File

@@ -0,0 +1,13 @@
Copyright (c) 2026 Z.ai All rights reserved.
Permission is granted for personal, educational, and non-commercial use only.
Commercial use is strictly prohibited without prior written permission from the author.
Unauthorized copying, modification, or distribution of the software for commercial purposes is prohibited.
The author reserves the right to make the final determination of what constitutes "commercial use".
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY ARISING FROM THE USE OF THE SOFTWARE.

436
skills/ppt/SKILL.md Executable file
View File

@@ -0,0 +1,436 @@
---
name: ppt
metadata:
author: Z.AI
version: "1.0"
description: "Presentation creation, editing, and analysis for .pptx files: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes. Academic/paper-based presentations use the embedded Beamer module at end of this file (PDF output only)."
license: Proprietary. LICENSE.txt has complete terms
---
# PPT creation, editing, and analysis
## Quick Setup
```bash
bash "$SKILL_DIR/setup.sh" # Interactive environment check + install
```
---
## Routing: Academic / Paper-Based Presentations → Beamer
> **STOP — check this before doing any work.**
>
> If the request matches **any** trigger below, **skip the PPTX workflow entirely**.
> Read **[`beamer.md`](beamer.md)** in this directory and follow its instructions.
| Trigger | Typical phrasing |
|---------|-----------------|
| Reading / summarizing a paper to make slides | "read this PDF and make slides", "make slides from this paper" |
| Academic / scientific / research presentation | "conference talk", "research presentation", "academic presentation" |
| Thesis or dissertation defense | "thesis defense", "proposal defense", "defense slides" |
| Any scholarly audience presentation | "academic PPT", "paper presentation", "research talk" |
| STEM / science courseware | "STEM slides", "science lecture", "math/physics/chemistry courseware" |
| User mentions a "paper" or "thesis" in any language | "present this paper", "talk about this thesis", "summarize this article into slides" |
| Uploaded file is clearly an academic paper | "make slides from this", "help me present this" — where the uploaded PDF contains academic indicators (abstract, keywords, references, DOI, author affiliations, journal name) in the first 3 pages |
> **Beamer output format: PDF-style slides only.**
>
> **Routing decision rule:** The trigger table above applies to **all languages**. For non-English requests, match by semantic meaning — mentally translate the user's intent into English and check against the triggers.
>
> **Important:** In many languages (e.g., Chinese, Japanese, Korean), "PPT" is a generic colloquial word for "slides" or "presentation" — it does NOT indicate a preference for `.pptx` format. Only route to the PPTX workflow when the user **explicitly** requests `.pptx` format (e.g., "I need a .pptx file", "export as pptx") or the content is clearly non-academic (e.g., marketing, business, teaching children).
---
## Overview
A user may ask you to create, edit, or analyze the contents of a .pptx file. A .pptx file is essentially a ZIP archive containing XML files and other resources that you can read or edit. You have different tools and workflows available for different tasks.
## Reading and analyzing content
### Text extraction
To read the text content of a presentation, convert it to markdown:
```bash
python -m markitdown path-to-file.pptx
```
### Raw XML access
For comments, speaker notes, slide layouts, animations, design elements, or complex formatting, unpack the presentation and inspect its raw XML.
#### Unpacking a file
```
python ooxml/scripts/unpack.py <office_file> <output_dir>
```
**Note**: `unpack.py` is at `skills/pptx/ooxml/scripts/unpack.py` relative to the project root. If not found, run `find . -name "unpack.py"` to locate it.
#### Key file structures
| Path | Contents |
|------|----------|
| `ppt/presentation.xml` | Main metadata and slide references |
| `ppt/slides/slide{N}.xml` | Per-slide content |
| `ppt/notesSlides/notesSlide{N}.xml` | Speaker notes |
| `ppt/comments/modernComment_*.xml` | Slide comments |
| `ppt/slideLayouts/` | Layout templates |
| `ppt/slideMasters/` | Master slide templates |
| `ppt/theme/` | Theme and styling |
| `ppt/media/` | Images and other media |
#### Typography and color extraction
**When emulating an existing design**, extract typography and colors before starting:
1. **Theme file**`ppt/theme/theme1.xml`: colors (`<a:clrScheme>`), fonts (`<a:fontScheme>`)
2. **Slide content**`ppt/slides/slide1.xml`: actual font usage (`<a:rPr>`) and colors
3. **Global search** — grep for `<a:solidFill>`, `<a:srgbClr>`, and font references across all XML files
---
## Creating a new PowerPoint presentation **using a template**
When the user upload a pptx file,and do not ask you to create a fully new pptx,you must create a presentation that follows an existing template's design, you'll need to duplicate and re-arrange template slides before then replacing placeholder content.
### Workflow
1. **Extract template text AND create visual thumbnail grid**:
* Extract text: `python -m markitdown template.pptx > template-content.md`
* Read `template-content.md`: Read the entire file. **NEVER set any range limits.**
* Create thumbnail grids: `python scripts/thumbnail.py template.pptx`
* See [Creating Thumbnail Grids](#creating-thumbnail-grids) section for details
2. **Analyze template and save inventory to a file**:
* **Visual Analysis**: Review thumbnail grid(s) to understand layouts and design patterns
* Create and save `template-inventory.md` containing:
```markdown
# Template Inventory Analysis
**Total Slides: [count]**
**IMPORTANT: Slides are 0-indexed (first slide = 0, last slide = count-1)**
## [Category Name]
- Slide 0: [Layout code if available] - Description/purpose
- Slide 1: [Layout code] - Description/purpose
[... EVERY slide must be listed ...]
```
3. **Create presentation outline based on template inventory**:
* Choose layouts that match your content structure
* **CRITICAL: Match layout structure to actual content**:
- Single-column layouts: Use for unified narrative or single topic
- Two-column layouts: Use ONLY when you have exactly 2 distinct items
- Three-column layouts: Use ONLY when you have exactly 3 distinct items
- Image + text layouts: Use ONLY when you have actual images
- Count your actual content pieces BEFORE selecting layout
* Save `outline.md` with content AND template mapping
4. **Duplicate, reorder, and delete slides using `rearrange.py`**:
```bash
python scripts/rearrange.py template.pptx working.pptx 0,34,34,50,52
```
5. **Extract ALL text using the `inventory.py` script**:
```bash
python scripts/inventory.py working.pptx text-inventory.json
```
Read `text-inventory.json` entirely. **NEVER set range limits.**
6. **Generate replacement text and save to JSON file**:
- Verify which shapes exist in inventory — only reference shapes that are present
- Add `"paragraphs"` field to shapes that need content
- **ALL text shapes from inventory will be cleared** unless you provide "paragraphs"
- Paragraphs with bullets are automatically left-aligned
- **Do NOT include bullet symbols** (bullet, -, *) in text — they're added automatically
- Save to `replacement-text.json`
**CRITICAL — JSON generation rules (learned from practice):**
- **Always use `json.dump()` to write the file** — never write raw JSON strings in Python code.
Raw strings may embed unescaped `"` characters (e.g. `"三遥"`, `"线上+线下"`) that silently
break JSON parsing. `json.dump(data, f, ensure_ascii=False, indent=2)` handles all escaping
automatically.
- **Respect small box character limits** — check `width` and `font_size` from inventory before
writing text for numeric/label shapes. A box of `width ≤ 0.7"` at `font_size ≥ 16pt` can hold
roughly 34 characters max. Keep percentage values like `"99.7%"` to ≤ 4 chars, or shorten
(e.g. `"100%"` instead of `"99.96%"`).
- **Match replacement length to original** — for body text boxes, count characters in the
original inventory text. Replacements significantly longer than the original will overflow.
When in doubt, err shorter rather than longer.
- **Test incrementally** — validate with a 5-slide subset before writing the full deck.
`replace.py` blocks on overflow errors; fix them slide-by-slide rather than all at once.
7. **Apply replacements**:
```bash
python scripts/replace.py working.pptx replacement-text.json output.pptx
```
## Creating a new PowerPoint presentation **without a template**
When creating a new PowerPoint presentation from scratch, use the **Design System + Component** workflow.
### Step 0 — Scene Classification (MANDATORY)
Before ANY design work, classify the presentation into one of the five scenes below:
| Scene | Keywords / Triggers |
|-------|-------------------|
| **Teaching / Training** | course, teaching, training, lecture, courseware, knowledge points, lesson plan |
| **Work Report / Review** | report, review, summary, retrospective, OKR, KPI, quarterly, annual |
| **Proposal / Pitch** | proposal, plan, pitch, investor, roadshow, business plan |
| **Thesis Defense / Academic** | thesis, defense, research, academic, topic, graduation project — **→ if source is a paper/PDF or audience is academic, read [`beamer.md`](beamer.md) instead** |
| **General** | None of the above, or user did not specify |
### Step 1 — Select Theme (MANDATORY)
Read [`themes.md`](themes.md) and select a theme based on scene and content tone.
**Output**: State your chosen theme name, your chosen **accent variant** (A/B/C), and the full color palette (primary-80, primary-90, primary-5, accent, etc.) before writing any code.
**Accent variant selection**: Each theme offers 3 accent colors (A = default, B, C). Choose the variant that best matches the content tone. You may also mix — e.g., use accent-A for most slides and accent-B for emphasis pages — but keep the primary palette constant.
Theme selection tips:
- Work report → Ocean or Graphite
- Proposal / pitch → Ocean, Sandstone, or Twilight
- Teaching / courseware → Forest or Ocean
- Thesis defense → read [`beamer.md`](beamer.md) (PDF output); if `.pptx` is explicitly required, use Graphite or Forest
- Tech keynote / product launch → Deep Mineral or Mono
- Cultural / lifestyle / brand → Warm Retro
- ESG / sustainability → Deep Forest or Forest
- Consumer / lifestyle / female audience → Coral
- Healthcare / wellness / eco → Mint
- SaaS / AI / onboarding → Azure
- Annual events / launches / high-energy → Ember
- General → any theme that fits the content
**After selecting a theme, note its Image Keywords and Mask Color** — you will need them in Step 5.5.
### Step 2 — Read Design System (MANDATORY)
Read [`design-system.md`](design-system.md). Understand the color system (mandatory) and creative principles (guidelines). The color scale is the only hard constraint — everything else (spacing, font sizes, layout) is flexible.
### Step 3 — Read HTML-to-PPTX Guide (MANDATORY)
Read [`html2pptx.md`](html2pptx.md) completely from start to finish. **NEVER set any range limits when reading this file.**
### Step 4 — Plan Slide Sequence
For each slide, decide:
1. Which **component** from [`components.md`](components.md) to use as a starting point (or design from scratch)
2. What **content** to fill in — **be generous with content; fill the slide**
3. How to **remix** the component — change spacing, font sizes, card styles, backgrounds, proportions to create variety
**KEY PRINCIPLES**:
- Read [`components.md`](components.md) for available starting points
- Also read [`data-viz-components.md`](data-viz-components.md) for data visualization components
- **Adjacent slides MUST look distinctly different** — vary layout structure, background, card treatment
- **Fill the slide**: Avoid large empty areas. If content is sparse, use larger typography, more generous spacing, bigger visual elements, or add decorative elements to create visual richness
- **Every content slide should have at least one non-text visual element** (color block, stat number, chart, icon, accent bar, photo, shape)
- Alternate between high-density and low-density pages for rhythm
- Use data visualization components when content contains numbers, comparisons, percentages
- **Tables are a great way to enrich content** — use `content-table*` or `content-chart-*` from components.md whenever content involves structured data, feature comparisons, schedules, or multi-attribute lists
**Anti-whitespace strategies** (use when a slide feels empty):
- Increase font sizes (e.g., body from 15pt to 17pt, headings from 22pt to 26pt)
- Add colored background blocks or sections
- Use a darker or tinted background instead of pure white
- Add decorative elements (accent bars, shapes, gradient bands)
- Expand card padding and spacing
- Use a photo background with mask overlay
- Switch from a text-heavy layout to a visual-heavy one
**Note: Not all whitespace is bad.** KPI pages, quote pages, and big-number focus pages are *designed* to have generous whitespace — that's intentional emphasis. Only fix whitespace on content-heavy pages (bullet lists, card grids, text blocks) where it looks accidental. See design-system.md §2.2 for the full distinction.
**Slide sequence pattern** (recommended):
```
1. Cover → PREFER cover-photo-mask (with downloaded photo + theme mask)
→ Fallback: cover-dark-hero (no photo needed) or cover-split
2. TOC → toc-card-grid (surface bg) / toc-big-number (visual variety)
3. Section divider (optional) → divider-photo-mask (different photo from cover)
→ or divider-gradient / divider-bold-center
4. Content page A → light background, visually rich component
5. Content page B → ★ DARK BACKGROUND ★ (content-dark-bullets / dark-kpi / dark-split)
6. Section divider (optional) → different variant from #3
7. Content page C → image-based (split-text-visual, photo-cards, etc.)
8. Content page D → data-focused (kpi-row, big-number-focus, etc.)
9. Closing → dark background echoing cover color
Background rhythm target: ~40% white, ~25% surface/tinted, ~20% dark, ~15% photo
```
### Step 5 — Generate HTML from Components
For each slide:
1. Start from a component template in `components.md`, or design from scratch
2. Replace all `${variable}` placeholders with actual theme color values
3. Replace placeholder text with actual content
4. Adjust element count (add/remove cards, list items) as needed
5. **Before writing each slide's HTML**: Check the **Card Style Cookbook** at the top of components.md. Pick a different card style from the previous slide. Also check if this slide should use a **Dark Background Content Template**.
6. **Be creative**: Freely modify spacing, font sizes, card styles, proportions, background treatments, and decorative elements across pages. The only hard constraints are the html2pptx engine limitations (no flex-wrap, no negative margins, no DIV background-image, no CSS gradients). Use the design-system.md Quick Reference for suggested ranges, but treat them as starting points, not limits.
- **Card styles**: Use the **Card Style Cookbook** in components.md to swap between shadow/outline/solid/accent-bar/dark card styles. No 2 adjacent slides should use the same card style.
- **Title bars**: All content slides must use the **same header style** — pick one title bar variant from components.md and apply it consistently across every content page.
- **Dark pages**: Use the **Dark Background Content Templates** in components.md for rhythm-breaking dark slides. Aim for at least 1 dark content page per 4 slides.
6. **Fill the slide**: If there's visible empty space, increase font sizes, add visual elements, expand padding, or use a colored/photo background. A well-filled slide looks professional; excessive whitespace looks unfinished.
### Step 5.8 — Visual Diversity Check (RECOMMENDED)
Before converting to PPTX, do a quick scan of your slide sequence:
- Are adjacent slides visually distinct (different layout, background, card style)?
- Is there enough variety across the deck (multiple layout structures, card treatments, background approaches)?
- Is there at least one dramatic "rhythm breaker" page?
- Do real photographs appear on covers and at least one other slide?
If the answer to any is "no", revise before proceeding.
### Step 6 — Convert and Validate
1. Create and run a JavaScript file using [`html2pptx.js`](scripts/html2pptx.js) to convert HTML slides to PowerPoint:
```javascript
const pptxgen = require('pptxgenjs');
const html2pptx = require('./html2pptx');
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_16x9';
// Optional: custom font configuration
const fontConfig = { cjk: 'Microsoft YaHei', latin: 'Corbel' };
// Process ALL slides with warnings collection
const allWarnings = [];
for (const htmlFile of slideFiles) {
const { slide, placeholders, warnings } = await html2pptx(htmlFile, pptx, { fontConfig });
allWarnings.push(...warnings);
}
// Add charts to placeholder areas if any
if (placeholders.length > 0) {
slide.addChart(pptx.charts.LINE, chartData, placeholders[0]);
}
await pptx.writeFile('output.pptx');
```
2. **Check warnings**: Review `warnings` output. **Blocking issues** (overflow, font < 11pt) must be fixed. **Non-blocking warnings** (bounds, balance, density) are suggestions — use judgment on whether to fix them.
3. **Visual validation**: Generate thumbnails and inspect for layout issues:
```bash
python scripts/thumbnail.py output.pptx workspace/thumbnails --cols 4
```
- Read and carefully examine the thumbnail image for:
- **Text cutoff**: Text being cut off by header bars, shapes, or slide edges
- **Text overlap**: Text overlapping with other text or shapes
- **Positioning issues**: Content too close to slide boundaries or other elements
- **Contrast issues**: Insufficient contrast between text and backgrounds
- **Consistency check**: All body text same font and size? All page margins consistent? All content slides use the same header style?
- If issues found, adjust HTML and regenerate
- Repeat until all slides are visually correct
### Step 6.5 — Final Quality Check (RECOMMENDED)
Before finalizing, do a quick visual quality scan:
- ✅ Real photographs used (cover + at least 1 other slide)
- ✅ Background variety (at least 3 different treatments)
- ✅ No 2 consecutive slides look the same
- ✅ Multiple layout structures used (aim for 5+)
- ✅ Card styles vary across pages
- ✅ Every slide has a clear visual focal point
- ✅ At least 1 dramatic full-bleed or dark page exists
- ✅ All referenced image files exist and are > 10KB
If major issues are found, fix and regenerate. Minor imperfections are acceptable — don't over-optimize at the cost of creativity.
### Design Hard Rules (ALWAYS ENFORCED)
These rules are split into **engine constraints** (violating them causes broken output) and **design principles** (ensuring quality).
**Engine Constraints (technical — cannot be violated):**
```
[ENGINE] Slide canvas is 720×405pt — content exceeding this overflows
[ENGINE] All colors must come from the theme color scale — no arbitrary grays (#666 #999 #DDD)
[ENGINE] font-family must include a CJK font name to trigger correct mapping
[ENGINE] Do not use flex-wrap — multi-row layouts must use separate flex containers
[ENGINE] Do not use negative margins — they cause text stacking in PPT
[ENGINE] Multi-column equal-width cards must use fixed width + flex-shrink:0, not flex:1
[ENGINE] Background images only work on <body>, not <div> — DIV background-image is not supported
[ENGINE] Images must be local file paths, not URLs
[ENGINE] Titles and short labels (<10 characters) should use white-space:nowrap
[ENGINE] Numeric sequences (e.g. 01/02/03, $12M) should use white-space:nowrap
```
**Design Principles (creative quality — strongly encouraged):**
```
[DESIGN] Adjacent slides should use different layouts, backgrounds, and card styles
[DESIGN] Every content slide should have at least one visual focal point
[DESIGN] Cover and closing page should echo each other
[DESIGN] Prefer cutting content over shrinking fonts — only when a slide is already well-filled and overflow is imminent; never cut content preemptively
[DESIGN] Aim for 5+ layout structures, 3+ card styles, 3+ background treatments across the deck
[DESIGN] Insert a rhythm-breaking page every 3-4 slides
[DESIGN] Background images should have a mask overlay for text readability
[DESIGN] Content should be vertically balanced, not crammed at the top
[DESIGN] Accent colors must have HSL saturation ≤ 65% — high-saturation colors look garish on projection
[DESIGN] Large color blocks (>15% page area) should use S ≤ 50% — only small accents can be vivid
[DESIGN] All content slides must use the same header style — pick one title bar variant and apply it consistently across all content pages
```
---
## Editing an existing PowerPoint presentation
When editing slides in an existing PowerPoint presentation, work with raw Office Open XML (OOXML) format.
### Workflow
1. **MANDATORY - READ ENTIRE FILE**: Read [`ooxml.md`](ooxml.md) (~500 lines) completely from start to finish. **NEVER set any range limits when reading this file.**
2. Unpack the presentation: `python ooxml/scripts/unpack.py <office_file> <output_dir>`
3. Edit the XML files (primarily `ppt/slides/slide{N}.xml` and related files)
4. **CRITICAL**: Validate immediately after each edit: `python ooxml/scripts/validate.py <dir> --original <file>`
5. Pack the final presentation: `python ooxml/scripts/pack.py <input_directory> <office_file>`
## Creating Thumbnail Grids
```bash
python scripts/thumbnail.py template.pptx [output_prefix]
```
**Features**:
- Creates: `thumbnails.jpg` (or `thumbnails-1.jpg`, `thumbnails-2.jpg` for large decks)
- Default: 5 columns, max 30 slides per grid (5x6)
- Custom prefix: `python scripts/thumbnail.py template.pptx my-grid`
- Adjust columns: `--cols 4` (range: 3-6)
- Slides are zero-indexed (Slide 0, Slide 1, etc.)
## Converting Slides to Images
1. **Convert PPTX to PDF**:
```bash
soffice --headless --convert-to pdf template.pptx
```
2. **Convert PDF pages to JPEG images**:
```bash
pdftoppm -jpeg -r 150 template.pdf slide
```
## Code Style Guidelines
**IMPORTANT**: When generating code for PPTX operations:
- Write concise code
- Avoid verbose variable names and redundant operations
- Avoid unnecessary print statements
## Dependencies
Required dependencies (should already be installed):
- **markitdown**: `pip install "markitdown[pptx]"` (text extraction)
- **pptxgenjs**: `npm install -g pptxgenjs` (creating presentations)
- **playwright**: `npm install -g playwright` (HTML rendering)
- **react-icons**: `npm install -g react-icons react react-dom` (icons)
- **sharp**: `npm install -g sharp` (SVG rasterization and image processing)
- **LibreOffice**: `sudo apt-get install libreoffice` (PDF conversion)
- **Poppler**: `sudo apt-get install poppler-utils` (pdftoppm)
- **defusedxml**: `pip install defusedxml` (secure XML parsing)

1461
skills/ppt/beamer.md Executable file

File diff suppressed because it is too large Load Diff

1671
skills/ppt/components.md Executable file

File diff suppressed because it is too large Load Diff

529
skills/ppt/data-viz-components.md Executable file
View File

@@ -0,0 +1,529 @@
# Data Visualization Components — Supplement to components.md
These components use **pure HTML+CSS** to render charts and data visualizations without relying on PptxGenJS chart API. They convert directly through html2pptx into shapes.
**When to use**: Prefer data visualization components whenever the content contains numbers, comparisons, percentages, or structured data. Every PPT with 6+ slides **MUST** include at least 1-2 data visualization pages.
**Selection principle**: Concrete data → prioritize data viz components (bars/tables/funnels/donuts) over plain text lists. Alternate between text pages and data pages for visual rhythm.
For PptxGenJS native charts (BAR/LINE/PIE/DOUGHNUT), use `content-chart-focus` with placeholder + `slide.addChart()` in compile.js.
---
<a id="content-horizontal-bars"></a>
### content-horizontal-bars — Horizontal Bar Comparison
`data | medium | light | none`
Multi-item value comparison. Best for: market share, KPI benchmarks, quarterly comparisons.
```html
<body style="width:720pt; height:405pt; margin:0; padding:0; overflow:hidden;
background-color:${background};
font-family:'Microsoft YaHei',sans-serif;
display:flex; flex-direction:column;">
<div style="width:720pt; height:56pt; background:${primary-90};
display:flex; align-items:center; padding:0 48pt;">
<h2 style="font-size:22pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1.25;">
Market Share Comparison
</h2>
</div>
<div style="flex:1; display:flex; flex-direction:column; justify-content:center; padding:0 48pt; gap:20pt;">
<!-- Bar item: repeat for each data point -->
<div style="display:flex; align-items:center; gap:12pt;">
<p style="font-size:13pt; color:${primary-80}; margin:0; width:100pt; line-height:1.3; white-space:nowrap;">Product A</p>
<div style="flex:1; height:24pt; background:${primary-10}; border-radius:4pt;">
<div style="height:24pt; width:70%; background:${primary-80}; border-radius:4pt;"></div>
</div>
<p style="font-size:15pt; font-weight:bold; color:${primary-80}; margin:0; width:48pt; text-align:right; line-height:1;">70%</p>
</div>
<div style="display:flex; align-items:center; gap:12pt;">
<p style="font-size:13pt; color:${primary-80}; margin:0; width:100pt; line-height:1.3; white-space:nowrap;">Product B</p>
<div style="flex:1; height:24pt; background:${primary-10}; border-radius:4pt;">
<div style="height:24pt; width:52%; background:${primary-60}; border-radius:4pt;"></div>
</div>
<p style="font-size:15pt; font-weight:bold; color:${primary-60}; margin:0; width:48pt; text-align:right; line-height:1;">52%</p>
</div>
<div style="display:flex; align-items:center; gap:12pt;">
<p style="font-size:13pt; color:${primary-80}; margin:0; width:100pt; line-height:1.3; white-space:nowrap;">Product C</p>
<div style="flex:1; height:24pt; background:${primary-10}; border-radius:4pt;">
<div style="height:24pt; width:38%; background:${primary-40}; border-radius:4pt;"></div>
</div>
<p style="font-size:15pt; font-weight:bold; color:${primary-40}; margin:0; width:48pt; text-align:right; line-height:1;">38%</p>
</div>
<div style="display:flex; align-items:center; gap:12pt;">
<p style="font-size:13pt; color:${primary-80}; margin:0; width:100pt; line-height:1.3; white-space:nowrap;">Product D</p>
<div style="flex:1; height:24pt; background:${primary-10}; border-radius:4pt;">
<div style="height:24pt; width:22%; background:${primary-20}; border-radius:4pt;"></div>
</div>
<p style="font-size:15pt; font-weight:bold; color:${primary-20}; margin:0; width:48pt; text-align:right; line-height:1;">22%</p>
</div>
</div>
</body>
```
**Variation**: Use `${accent}` for the highlighted/top bar to draw attention.
---
<a id="content-stacked-bars"></a>
### content-stacked-bars — Stacked Progress Bars
`data | medium | light | shadow`
Multi-dimension proportional data. Best for: budget allocation, resource distribution, composition analysis.
```html
<body style="width:720pt; height:405pt; margin:0; padding:0; overflow:hidden;
background-color:${background};
font-family:'Microsoft YaHei',sans-serif;
display:flex; flex-direction:column;">
<div style="width:720pt; height:56pt; background:${primary-90};
display:flex; align-items:center; padding:0 48pt;">
<h2 style="font-size:22pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1.25;">
Budget Allocation by Department
</h2>
</div>
<div style="flex:1; display:flex; flex-direction:column; justify-content:center; padding:0 48pt; gap:24pt;">
<div>
<div style="display:flex; justify-content:space-between; margin-bottom:8pt;">
<p style="font-size:15pt; font-weight:bold; color:${primary-80}; margin:0; line-height:1.3;">Q1 2024</p>
<p style="font-size:13pt; color:${primary-40}; margin:0; line-height:1;">$2.4M Total</p>
</div>
<div style="display:flex; height:32pt; border-radius:6pt; overflow:hidden;">
<div style="width:35%; background:${primary-80};"></div>
<div style="width:25%; background:${primary-60};"></div>
<div style="width:20%; background:${primary-40};"></div>
<div style="width:12%; background:${accent};"></div>
<div style="width:8%; background:${primary-20};"></div>
</div>
<div style="display:flex; gap:16pt; margin-top:8pt;">
<div style="display:flex; align-items:center; gap:4pt;">
<div style="width:8pt; height:8pt; background:${primary-80}; border-radius:2pt;"></div>
<p style="font-size:11pt; color:${primary-60}; margin:0; line-height:1;">R&D 35%</p>
</div>
<div style="display:flex; align-items:center; gap:4pt;">
<div style="width:8pt; height:8pt; background:${primary-60}; border-radius:2pt;"></div>
<p style="font-size:11pt; color:${primary-60}; margin:0; line-height:1;">Marketing 25%</p>
</div>
<div style="display:flex; align-items:center; gap:4pt;">
<div style="width:8pt; height:8pt; background:${primary-40}; border-radius:2pt;"></div>
<p style="font-size:11pt; color:${primary-60}; margin:0; line-height:1;">Sales 20%</p>
</div>
<div style="display:flex; align-items:center; gap:4pt;">
<div style="width:8pt; height:8pt; background:${accent}; border-radius:2pt;"></div>
<p style="font-size:11pt; color:${primary-60}; margin:0; line-height:1;">Ops 12%</p>
</div>
</div>
</div>
<div>
<div style="display:flex; justify-content:space-between; margin-bottom:8pt;">
<p style="font-size:15pt; font-weight:bold; color:${primary-80}; margin:0; line-height:1.3;">Q2 2024</p>
<p style="font-size:13pt; color:${primary-40}; margin:0; line-height:1;">$2.8M Total</p>
</div>
<div style="display:flex; height:32pt; border-radius:6pt; overflow:hidden;">
<div style="width:40%; background:${primary-80};"></div>
<div style="width:22%; background:${primary-60};"></div>
<div style="width:18%; background:${primary-40};"></div>
<div style="width:10%; background:${accent};"></div>
<div style="width:10%; background:${primary-20};"></div>
</div>
</div>
</div>
</body>
```
---
<a id="content-data-table"></a>
### content-data-table — Structured Data Table
`data | medium | light | none`
Multi-row multi-column structured data. Best for: quarterly reports, feature comparisons, competitive analysis.
```html
<body style="width:720pt; height:405pt; margin:0; padding:0; overflow:hidden;
background-color:${background};
font-family:'Microsoft YaHei',sans-serif;
display:flex; flex-direction:column;">
<div style="width:720pt; height:56pt; background:${primary-90};
display:flex; align-items:center; padding:0 48pt;">
<h2 style="font-size:22pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1.25;">
Quarterly Performance Summary
</h2>
</div>
<div style="flex:1; display:flex; flex-direction:column; justify-content:center; padding:0 48pt;">
<div style="display:flex; background:${primary-80}; border-radius:8pt 8pt 0 0; padding:12pt 16pt;">
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; width:120pt; line-height:1.3;">Department</p>
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; width:120pt; line-height:1.3; text-align:right;">Q1</p>
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; width:120pt; line-height:1.3; text-align:right;">Q2</p>
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; width:120pt; line-height:1.3; text-align:right;">Q3</p>
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; width:112pt; line-height:1.3; text-align:right;">Q4</p>
</div>
<div style="display:flex; background:${surface}; padding:10pt 16pt; border-left:1pt solid ${primary-10}; border-right:1pt solid ${primary-10};">
<p style="font-size:13pt; color:${primary-80}; margin:0; width:120pt; line-height:1.3;">Engineering</p>
<p style="font-size:13pt; color:${primary-60}; margin:0; width:120pt; line-height:1.3; text-align:right;">$1.2M</p>
<p style="font-size:13pt; color:${primary-60}; margin:0; width:120pt; line-height:1.3; text-align:right;">$1.5M</p>
<p style="font-size:13pt; color:${primary-60}; margin:0; width:120pt; line-height:1.3; text-align:right;">$1.8M</p>
<p style="font-size:13pt; color:${accent}; margin:0; width:112pt; line-height:1.3; text-align:right; font-weight:bold;">$2.1M</p>
</div>
<div style="display:flex; background:${background}; padding:10pt 16pt; border-left:1pt solid ${primary-10}; border-right:1pt solid ${primary-10};">
<p style="font-size:13pt; color:${primary-80}; margin:0; width:120pt; line-height:1.3;">Marketing</p>
<p style="font-size:13pt; color:${primary-60}; margin:0; width:120pt; line-height:1.3; text-align:right;">$800K</p>
<p style="font-size:13pt; color:${primary-60}; margin:0; width:120pt; line-height:1.3; text-align:right;">$920K</p>
<p style="font-size:13pt; color:${primary-60}; margin:0; width:120pt; line-height:1.3; text-align:right;">$1.1M</p>
<p style="font-size:13pt; color:${accent}; margin:0; width:112pt; line-height:1.3; text-align:right; font-weight:bold;">$1.3M</p>
</div>
<div style="display:flex; background:${surface}; padding:10pt 16pt; border-left:1pt solid ${primary-10}; border-right:1pt solid ${primary-10};">
<p style="font-size:13pt; color:${primary-80}; margin:0; width:120pt; line-height:1.3;">Sales</p>
<p style="font-size:13pt; color:${primary-60}; margin:0; width:120pt; line-height:1.3; text-align:right;">$2.0M</p>
<p style="font-size:13pt; color:${primary-60}; margin:0; width:120pt; line-height:1.3; text-align:right;">$2.3M</p>
<p style="font-size:13pt; color:${primary-60}; margin:0; width:120pt; line-height:1.3; text-align:right;">$2.5M</p>
<p style="font-size:13pt; color:${accent}; margin:0; width:112pt; line-height:1.3; text-align:right; font-weight:bold;">$2.8M</p>
</div>
<div style="display:flex; background:${primary-10}; padding:10pt 16pt; border-radius:0 0 8pt 8pt;">
<p style="font-size:13pt; color:${primary-80}; margin:0; width:120pt; line-height:1.3; font-weight:bold;">Total</p>
<p style="font-size:13pt; color:${primary-80}; margin:0; width:120pt; line-height:1.3; text-align:right; font-weight:bold;">$4.0M</p>
<p style="font-size:13pt; color:${primary-80}; margin:0; width:120pt; line-height:1.3; text-align:right; font-weight:bold;">$4.7M</p>
<p style="font-size:13pt; color:${primary-80}; margin:0; width:120pt; line-height:1.3; text-align:right; font-weight:bold;">$5.4M</p>
<p style="font-size:13pt; color:${accent}; margin:0; width:112pt; line-height:1.3; text-align:right; font-weight:bold;">$6.2M</p>
</div>
</div>
</body>
```
---
<a id="content-quadrant-matrix"></a>
### content-quadrant-matrix — 2x2 Quadrant Matrix
`data | medium | light | none`
Two-axis classification framework. Best for: BCG matrix, priority matrix, SWOT, evaluation frameworks.
```html
<body style="width:720pt; height:405pt; margin:0; padding:0; overflow:hidden;
background-color:${background};
font-family:'Microsoft YaHei',sans-serif;
display:flex; flex-direction:column;">
<div style="width:720pt; height:56pt; background:${primary-90};
display:flex; align-items:center; padding:0 48pt;">
<h2 style="font-size:22pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1.25;">
Priority Matrix
</h2>
</div>
<div style="flex:1; display:flex; padding:8pt 48pt 0 48pt;">
<div style="width:24pt; display:flex; align-items:center; justify-content:center;">
<p style="font-size:9pt; color:${primary-40}; margin:0; writing-mode:vertical-rl; transform:rotate(180deg); text-align:center; line-height:1.2;">Impact</p>
</div>
<div style="flex:1; display:flex; flex-direction:column;">
<div style="display:flex; gap:16pt; margin-bottom:16pt;">
<div style="width:296pt; flex-shrink:0; border-radius:10pt; padding:16pt 20pt; background:${primary-80};">
<p style="font-size:18pt; font-weight:bold; color:${on-dark}; margin:0 0 6pt 0; line-height:1.25;">Do First</p>
<p style="font-size:12pt; color:${on-dark-secondary}; margin:0; line-height:1.5;">High Impact + High Effort. Critical items requiring attention.</p>
</div>
<div style="width:296pt; flex-shrink:0; border-radius:10pt; padding:16pt 20pt; background:${surface}; border:1.5pt solid ${primary-20};">
<p style="font-size:18pt; font-weight:bold; color:${primary-80}; margin:0 0 6pt 0; line-height:1.25;">Quick Wins</p>
<p style="font-size:12pt; color:${primary-60}; margin:0; line-height:1.5;">High Impact + Low Effort. Prioritize for maximum ROI.</p>
</div>
</div>
<div style="display:flex; gap:16pt;">
<div style="width:296pt; flex-shrink:0; border-radius:10pt; padding:16pt 20pt; border:1.5pt solid ${primary-20};">
<p style="font-size:18pt; font-weight:bold; color:${primary-80}; margin:0 0 6pt 0; line-height:1.25;">Schedule</p>
<p style="font-size:12pt; color:${primary-60}; margin:0; line-height:1.5;">Low Impact + High Effort. Plan for later.</p>
</div>
<div style="width:296pt; flex-shrink:0; border-radius:10pt; padding:16pt 20pt; background:${primary-90};">
<p style="font-size:18pt; font-weight:bold; color:${on-dark}; margin:0 0 6pt 0; line-height:1.25;">Eliminate</p>
<p style="font-size:12pt; color:${on-dark-secondary}; margin:0; line-height:1.5;">Low Impact + Low Effort. Drop these tasks.</p>
</div>
</div>
<div style="margin-top:6pt;">
<p style="font-size:9pt; font-weight:bold; color:${primary-40}; margin:0; text-align:center;">LOW Effort &#8594; HIGH</p>
</div>
</div>
</div>
</body>
```
---
<a id="content-funnel"></a>
### content-funnel — Sales/Conversion Funnel
`data | medium | light | none`
Multi-stage progressive filtering. Best for: sales pipeline, conversion funnel, qualification process.
```html
<body style="width:720pt; height:405pt; margin:0; padding:0; overflow:hidden;
background-color:${background};
font-family:'Microsoft YaHei',sans-serif;
display:flex; flex-direction:column;">
<div style="width:720pt; height:56pt; background:${primary-90};
display:flex; align-items:center; padding:0 48pt;">
<h2 style="font-size:22pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1.25;">
Sales Conversion Funnel
</h2>
</div>
<div style="flex:1; display:flex; align-items:center; padding:0 48pt; gap:40pt;">
<div style="width:320pt; display:flex; flex-direction:column; align-items:center; gap:4pt;">
<div style="width:280pt; height:36pt; background:${primary-80}; border-radius:6pt; display:flex; align-items:center; justify-content:center;">
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1;">Leads: 10,000</p>
</div>
<div style="width:230pt; height:36pt; background:${primary-60}; border-radius:6pt; display:flex; align-items:center; justify-content:center;">
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1;">Qualified: 6,500</p>
</div>
<div style="width:180pt; height:36pt; background:${primary-40}; border-radius:6pt; display:flex; align-items:center; justify-content:center;">
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1;">Proposals: 3,200</p>
</div>
<div style="width:130pt; height:36pt; background:${accent}; border-radius:6pt; display:flex; align-items:center; justify-content:center;">
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1;">Negotiation: 1,800</p>
</div>
<div style="width:80pt; height:36pt; background:${primary-80}; border-radius:6pt; display:flex; align-items:center; justify-content:center;">
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1;">Closed: 850</p>
</div>
</div>
<div style="flex:1; display:flex; flex-direction:column; justify-content:center; gap:16pt;">
<div style="background:${surface}; border-radius:8pt; padding:16pt; border-left:3pt solid ${accent};">
<p style="font-size:32pt; font-weight:bold; color:${accent}; margin:0; line-height:1; white-space:nowrap;">8.5%</p>
<p style="font-size:13pt; color:${primary-60}; margin:4pt 0 0 0; line-height:1.4;">Overall Conversion Rate</p>
</div>
<div style="background:${surface}; border-radius:8pt; padding:16pt;">
<p style="font-size:32pt; font-weight:bold; color:${primary-80}; margin:0; line-height:1; white-space:nowrap;">46%</p>
<p style="font-size:13pt; color:${primary-60}; margin:4pt 0 0 0; line-height:1.4;">Qualified to Proposal Rate</p>
</div>
</div>
</div>
</body>
```
---
<a id="content-before-after"></a>
### content-before-after — Before vs After Comparison
`data | medium | light | none`
Side-by-side comparison panels. Best for: optimization results, before/after, pros/cons.
```html
<body style="width:720pt; height:405pt; margin:0; padding:0; overflow:hidden;
background-color:${background};
font-family:'Microsoft YaHei',sans-serif;
display:flex; flex-direction:column;">
<div style="width:720pt; height:56pt; background:${primary-90};
display:flex; align-items:center; padding:0 48pt;">
<h2 style="font-size:22pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1.25;">
Before vs After Optimization
</h2>
</div>
<div style="flex:1; display:flex; padding:16pt 48pt 0 48pt; gap:16pt;">
<!-- Before -->
<div style="width:296pt; flex-shrink:0; background:${surface}; border-radius:10pt; padding:20pt 24pt;">
<div style="display:flex; align-items:center; gap:8pt; margin-bottom:16pt;">
<div style="width:28pt; height:28pt; border-radius:50%; background:${primary-40}; display:flex; align-items:center; justify-content:center;">
<p style="font-size:13pt; color:${on-dark}; margin:0; line-height:1; font-weight:bold;">B</p>
</div>
<p style="font-size:18pt; font-weight:bold; color:${primary-40}; margin:0; line-height:1.25;">Before</p>
</div>
<div style="display:flex; justify-content:space-between; padding:8pt 0; border-bottom:1pt solid ${primary-10};">
<p style="font-size:13pt; color:${primary-60}; margin:0; line-height:1.5;">Load Time</p>
<p style="font-size:13pt; font-weight:bold; color:${primary-80}; margin:0; line-height:1.5;">4.2s</p>
</div>
<div style="display:flex; justify-content:space-between; padding:8pt 0; border-bottom:1pt solid ${primary-10};">
<p style="font-size:13pt; color:${primary-60}; margin:0; line-height:1.5;">Bounce Rate</p>
<p style="font-size:13pt; font-weight:bold; color:${primary-80}; margin:0; line-height:1.5;">38%</p>
</div>
<div style="display:flex; justify-content:space-between; padding:8pt 0;">
<p style="font-size:13pt; color:${primary-60}; margin:0; line-height:1.5;">Conversion</p>
<p style="font-size:13pt; font-weight:bold; color:${primary-80}; margin:0; line-height:1.5;">2.1%</p>
</div>
</div>
<!-- After (accent border to highlight) -->
<div style="width:296pt; flex-shrink:0; background:${surface}; border-radius:10pt; padding:20pt 24pt; border:2pt solid ${accent};">
<div style="display:flex; align-items:center; gap:8pt; margin-bottom:16pt;">
<div style="width:28pt; height:28pt; border-radius:50%; background:${accent}; display:flex; align-items:center; justify-content:center;">
<p style="font-size:13pt; color:${on-dark}; margin:0; line-height:1; font-weight:bold;">A</p>
</div>
<p style="font-size:18pt; font-weight:bold; color:${primary-80}; margin:0; line-height:1.25;">After</p>
</div>
<div style="display:flex; justify-content:space-between; padding:8pt 0; border-bottom:1pt solid ${primary-10};">
<p style="font-size:13pt; color:${primary-60}; margin:0; line-height:1.5;">Load Time</p>
<p style="font-size:13pt; font-weight:bold; color:${accent}; margin:0; line-height:1.5;">1.8s</p>
</div>
<div style="display:flex; justify-content:space-between; padding:8pt 0; border-bottom:1pt solid ${primary-10};">
<p style="font-size:13pt; color:${primary-60}; margin:0; line-height:1.5;">Bounce Rate</p>
<p style="font-size:13pt; font-weight:bold; color:${accent}; margin:0; line-height:1.5;">22%</p>
</div>
<div style="display:flex; justify-content:space-between; padding:8pt 0;">
<p style="font-size:13pt; color:${primary-60}; margin:0; line-height:1.5;">Conversion</p>
<p style="font-size:13pt; font-weight:bold; color:${accent}; margin:0; line-height:1.5;">4.7%</p>
</div>
</div>
</div>
</body>
```
---
<a id="content-dashboard"></a>
### content-dashboard — Data Dashboard / KPI Grid
`data | medium | light | shadow`
Multi-metric overview. Best for: dashboards, weekly/monthly reports, KPI summaries.
```html
<body style="width:720pt; height:405pt; margin:0; padding:0; overflow:hidden;
background-color:${surface};
font-family:'Microsoft YaHei',sans-serif;
display:flex; flex-direction:column;">
<div style="width:720pt; height:56pt; background:${primary-90};
display:flex; align-items:center; padding:0 48pt;">
<h2 style="font-size:22pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1.25;">
Monthly Performance Dashboard
</h2>
</div>
<!-- Row 1: 3 large stats -->
<div style="display:flex; gap:16pt; padding:16pt 48pt 0 48pt;">
<div style="width:192pt; flex-shrink:0; background:${surface-card}; border-radius:10pt; padding:20pt; box-shadow:0 3pt 10pt rgba(0,0,0,0.08); text-align:center;">
<p style="font-size:40pt; font-weight:bold; color:${primary-80}; margin:0; line-height:1; white-space:nowrap;">$4.2M</p>
<p style="font-size:13pt; color:${primary-40}; margin:8pt 0 0 0; line-height:1.4;">Revenue</p>
<p style="font-size:11pt; color:${accent}; margin:8pt 0 0 0; line-height:1; font-weight:bold;">+12.3% vs last month</p>
</div>
<div style="width:192pt; flex-shrink:0; background:${surface-card}; border-radius:10pt; padding:20pt; box-shadow:0 3pt 10pt rgba(0,0,0,0.08); text-align:center;">
<p style="font-size:40pt; font-weight:bold; color:${primary-80}; margin:0; line-height:1; white-space:nowrap;">2,847</p>
<p style="font-size:13pt; color:${primary-40}; margin:8pt 0 0 0; line-height:1.4;">Active Users</p>
<p style="font-size:11pt; color:${accent}; margin:8pt 0 0 0; line-height:1; font-weight:bold;">+8.7% vs last month</p>
</div>
<div style="width:192pt; flex-shrink:0; background:${surface-card}; border-radius:10pt; padding:20pt; box-shadow:0 3pt 10pt rgba(0,0,0,0.08); text-align:center;">
<p style="font-size:40pt; font-weight:bold; color:${primary-80}; margin:0; line-height:1; white-space:nowrap;">94.2%</p>
<p style="font-size:13pt; color:${primary-40}; margin:8pt 0 0 0; line-height:1.4;">Uptime</p>
<p style="font-size:11pt; color:${accent}; margin:8pt 0 0 0; line-height:1; font-weight:bold;">+0.3% vs last month</p>
</div>
</div>
<!-- Row 2: 4 smaller stats -->
<div style="display:flex; gap:16pt; padding:16pt 48pt;">
<div style="width:140pt; flex-shrink:0; background:${surface-card}; border-radius:8pt; padding:14pt; box-shadow:0 3pt 10pt rgba(0,0,0,0.08); text-align:center;">
<p style="font-size:32pt; font-weight:bold; color:${primary-60}; margin:0; line-height:1; white-space:nowrap;">156</p>
<p style="font-size:11pt; color:${primary-40}; margin:6pt 0 0 0; line-height:1.4;">New Signups</p>
</div>
<div style="width:140pt; flex-shrink:0; background:${surface-card}; border-radius:8pt; padding:14pt; box-shadow:0 3pt 10pt rgba(0,0,0,0.08); text-align:center;">
<p style="font-size:32pt; font-weight:bold; color:${primary-60}; margin:0; line-height:1; white-space:nowrap;">$148</p>
<p style="font-size:11pt; color:${primary-40}; margin:6pt 0 0 0; line-height:1.4;">Avg Revenue/User</p>
</div>
<div style="width:140pt; flex-shrink:0; background:${surface-card}; border-radius:8pt; padding:14pt; box-shadow:0 3pt 10pt rgba(0,0,0,0.08); text-align:center;">
<p style="font-size:32pt; font-weight:bold; color:${primary-60}; margin:0; line-height:1; white-space:nowrap;">4.6</p>
<p style="font-size:11pt; color:${primary-40}; margin:6pt 0 0 0; line-height:1.4;">NPS Score</p>
</div>
<div style="width:140pt; flex-shrink:0; background:${surface-card}; border-radius:8pt; padding:14pt; box-shadow:0 3pt 10pt rgba(0,0,0,0.08); text-align:center;">
<p style="font-size:32pt; font-weight:bold; color:${primary-60}; margin:0; line-height:1; white-space:nowrap;">23ms</p>
<p style="font-size:11pt; color:${primary-40}; margin:6pt 0 0 0; line-height:1.4;">Avg Response</p>
</div>
</div>
</body>
```
---
<a id="content-pyramid"></a>
### content-pyramid — Pyramid / Layered Hierarchy
`data | medium | light | none`
Layered hierarchy. Best for: Maslow pyramid, org levels, tech stack layers, priority hierarchy.
```html
<body style="width:720pt; height:405pt; margin:0; padding:0; overflow:hidden;
background-color:${background};
font-family:'Microsoft YaHei',sans-serif;
display:flex; flex-direction:column;">
<div style="width:720pt; height:56pt; background:${primary-90};
display:flex; align-items:center; padding:0 48pt;">
<h2 style="font-size:22pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1.25;">
Strategy Implementation Pyramid
</h2>
</div>
<div style="flex:1; display:flex; align-items:center; padding:0 48pt; gap:32pt;">
<div style="width:360pt; display:flex; flex-direction:column; align-items:center; gap:6pt;">
<div style="width:140pt; height:40pt; background:${primary-80}; border-radius:6pt; display:flex; align-items:center; justify-content:center;">
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1;">Vision &amp; Mission</p>
</div>
<div style="width:200pt; height:40pt; background:${primary-60}; border-radius:6pt; display:flex; align-items:center; justify-content:center;">
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1;">Strategic Objectives</p>
</div>
<div style="width:260pt; height:40pt; background:${primary-40}; border-radius:6pt; display:flex; align-items:center; justify-content:center;">
<p style="font-size:13pt; font-weight:bold; color:${on-dark}; margin:0; line-height:1;">Tactical Plans &amp; Programs</p>
</div>
<div style="width:320pt; height:40pt; background:${primary-20}; border-radius:6pt; display:flex; align-items:center; justify-content:center;">
<p style="font-size:13pt; font-weight:bold; color:${primary-80}; margin:0; line-height:1;">Operations &amp; Daily Execution</p>
</div>
</div>
<div style="flex:1; display:flex; flex-direction:column; justify-content:center; gap:20pt;">
<div style="border-left:2pt solid ${primary-80}; padding-left:12pt;">
<p style="font-size:13pt; font-weight:bold; color:${primary-80}; margin:0 0 4pt 0; line-height:1.3;">Top Level</p>
<p style="font-size:12pt; color:${primary-60}; margin:0; line-height:1.4;">Long-term direction, 5-10 year horizon</p>
</div>
<div style="border-left:2pt solid ${primary-60}; padding[left:12pt;">
<p style="font-size:13pt; font-weight:bold; color:${primary-80}; margin:0 0 4pt 0; line-height:1.3;">Strategy</p>
<p style="font-size:12pt; color:${primary-60}; margin:0; line-height:1.4;">3-5 year measurable targets</p>
</div>
<div style="border-left:2pt solid ${primary-40}; padding-left:12pt;">
<p style="font-size:13pt; font-weight:bold; color:${primary-80}; margin:0 0 4pt 0; line-height:1.3;">Tactics</p>
<p style="font-size:12pt; color:${primary-60}; margin:0; line-height:1.4;">1-2 year initiatives and projects</p>
</div>
<div style="border-left:2pt solid ${primary-20}; padding-left:12pt;">
<p style="font-size:13pt; font-weight:bold; color:${primary-80}; margin:0 0 4pt 0; line-height:1.3;">Operations</p>
<p style="font-size:12pt; color:${primary-60}; margin:0; line-height:1.4;">Daily tasks and short-term goals</p>
</div>
</div>
</div>
</body>
```

211
skills/ppt/design-system.md Executable file
View File

@@ -0,0 +1,211 @@
# Design System — PPT Creative Guidelines
This file provides **creative principles and a color system** for PPT design. Components and layouts should be inventive and diverse — these guidelines exist to ensure visual coherence, not to constrain creativity.
**Philosophy: Every slide is a design opportunity.** No two slides should look the same. Vary layouts, card treatments, backgrounds, typography weight, and whitespace aggressively. The audience should feel visual momentum, not repetition.
---
## 1. Color Scale System (Mandatory)
The color system is the **only hard constraint**. All colors used in the deck must derive from the chosen theme.
### 1.1 Color Scale Generation
Eight levels are derived from a single Primary color:
| Level | Lightness | Usage Examples |
|-------|-----------|---------------|
| `primary-100` | Darkest (L≈8%) | Dark backgrounds, dramatic pages |
| `primary-90` | Dark (L≈15%) | Title bars, dark blocks, overlays |
| `primary-80` | **Main color** | Headings, primary UI elements |
| `primary-60` | Medium dark (L≈45%) | Subheadings, icons, secondary elements |
| `primary-40` | Medium light (L≈60%) | Muted text, dividers, subtle accents |
| `primary-20` | Light (L≈80%) | Borders, light decorations, tints |
| `primary-10` | Very light (L≈90%) | Card fills, surface backgrounds |
| `primary-5` | Near white (L≈96%) | Page tints, hover states, subtle surfaces |
**Generation method**: From the Primary HSL (H, S, L) — keep H constant; dark levels S×1.1, light levels S×0.3; assign L per the table.
### 1.2 Semantic Colors
| Token | Value | Purpose |
|-------|-------|---------|
| `background` | `#FFFFFF` | Default page base |
| `surface` | `primary-5` | Tinted content area base |
| `surface-card` | `#FFFFFF` | Card base (floats above surface) |
| `text-primary` | `primary-80` | Primary text |
| `text-secondary` | `primary-60` | Secondary text |
| `text-muted` | `primary-40` | Annotations, footnotes |
| `on-dark` | `#FFFFFF` | Text on dark backgrounds |
| `on-dark-secondary` | `rgba(255,255,255,0.7)` | Secondary text on dark backgrounds |
| `border` | `primary-10` | Dividers, borders |
| `accent` | Defined by theme | Highlight color |
| `on-accent` | `#FFFFFF` | Text on accent color |
### 1.3 Color Rules
- **All grays must derive from the primary color scale** — no arbitrary `#666`, `#999`, `#DDD`
- **Text on dark areas must use `on-dark`** (#FFFFFF) — never use light primary tints on dark backgrounds
- **Accent color area**: ≤15% on standard pages; up to 40% on emphasis/transition pages
- **Saturation limit**: Accent colors should have HSL saturation ≤ 65% for most themes. High-energy themes (Deep Mineral, Ember, Mono) may use S ≤ 75% to preserve their intended vibrancy. Colors above S=80% look garish on projected slides. The theme presets already comply; if creating custom colors, check saturation.
- **Large color blocks** (>15% of page area): reduce saturation further (S ≤ 50%) to avoid visual fatigue. Use higher saturation only for small accents (bars, icons, small badges).
---
## 2. Creative Principles (Guidelines, Not Rules)
These are high-level design intentions. Interpret them freely.
### 2.1 Visual Diversity
- **No two adjacent slides should share the same layout, background treatment, or card style.** This is the single most important principle.
- Aim for **5+ distinct layout structures** across a deck (split columns, grids, single-focus, full-bleed, asymmetric, timeline, staggered, etc.)
- Aim for **3+ card styles** (shadow float, outline, solid fill, gradient, frosted glass, tag-style, image-backed, borderless, etc.)
- Aim for **3+ background treatments** (pure white, tinted surface, dark full-bleed, photo + mask, gradient, diagonal split, corner decoration, color band, etc.)
### 2.1.1 Deck-Wide Consistency Rules
**What MUST stay uniform across the entire deck** (changing these = unprofessional):
- Body text font and font size (e.g., always 15pt Microsoft YaHei)
- Page left/right margins (e.g., always 48pt)
- Primary color palette (same theme throughout)
- Accent color (same accent variant throughout, or intentional A/B mixing as documented)
**What SHOULD vary across slides** (sameness = monotony):
- Layout structure (grid, split, list, focus, timeline, etc.)
- Background treatment (white, surface, dark, photo, gradient)
- Card style (shadow, outline, solid, accent-bar, dark card)
- Title bar style (dark bar, accent bar, underline, inline title, vertical band)
- Decorative elements (accent bars, shapes, circles, dot patterns)
**The boundary is clear: base typography and spacing = consistent; visual composition = diverse.**
### 2.2 Intentional vs Accidental Whitespace
Not all whitespace is bad. The key is **intent**.
**Intentional whitespace (good — preserve it):**
- KPI / big-number pages: Large number centered with breathing room → dramatic focus
- Quote / pullout pages: Single sentence with generous margins → elegant emphasis
- Photo + caption pages: Image dominates, text is minimal → visual storytelling
- Title / divider pages: Bold text with open space → transition signal
**Accidental whitespace (bad — fix it):**
- Bullet list with 3 items occupying only 1/3 of the slide → expand or add visuals
- Card grid with small cards clustered at the top, bottom 60% empty → enlarge cards, increase padding
- Text block in the upper-left corner with nothing else on the page → redistribute content
**Rule of thumb**: If the whitespace makes the slide feel "unfinished" or "forgot to add content," it's accidental. If it makes the slide feel "clean" or "focused," it's intentional.
### 2.3 Visual Rhythm
- Alternate between high-density and low-density pages
- Insert a "rhythm breaker" every 3-4 slides — a page that looks dramatically different (full-bleed dark, photo overlay, large single quote, bold color block)
- Cover and closing page should echo each other in color or mood
- **Vary the page header treatment** — don't use the same dark title bar on every slide. Alternatives:
- Accent-colored bar (e.g., `background:${accent}`)
- Transparent header with large colored text and a bottom divider line
- No header bar at all — use oversized inline heading text
- Left-side vertical color band instead of top horizontal bar
- Gradient header (dark-to-transparent from top)
### 2.4 Typography
- **Hierarchy is king**: Headings should be visually distinct from body text through size, weight, and/or color
- Body text should be readable at projection distance — don't go below ~13pt
- Let type breathe — generous line-height makes everything feel more designed
- KPI / hero numbers should be oversized and bold to create a focal point
- Prefer cutting content over shrinking fonts — only when a slide is already well-filled and overflow is imminent; never cut content preemptively
### 2.5 Spacing & Layout
- Use consistent margins across the deck (recommended: 48pt left/right, 40pt top, ≥36pt bottom safe zone)
- Content should be **vertically balanced** — not crammed at the top with empty space below
- Give elements room — tight packing reads as "cheap"
- Fixed widths for multi-column cards prevent uneven stretching
### 2.6 Decoration & Visual Interest
- Every content slide should have **at least one non-text visual element** — accent bar, color block, photo, shape, large number, chart
- Decorative elements (circles, bars, geometric shapes, dot patterns) add polish and visual rhythm
- Decoration should support the content, never compete with it
### 2.7 Imagery
- Real photographs dramatically elevate quality — use them on covers, dividers, and visual pages
- Background images need a semi-transparent mask overlay for text readability
- Image tone (warm/cool) should match the theme atmosphere
---
## 3. Technical Constraints (html2pptx Engine)
These are **rendering engine limitations**, not design choices. Violating them causes broken output.
| Constraint | Reason |
|-----------|--------|
| Slide canvas: 720×405pt (16:9) | Fixed PPTX dimensions |
| `background-image` only works on `<body>`, not on `<div>` | html2pptx engine limitation |
| Don't use `flex-wrap` for multi-row grids — use separate flex containers per row | html2pptx drops wrapped rows |
| Don't use negative margins | Causes text stacking in PPT (elements become independent text boxes) |
| `font-family` must include a CJK font name | Required for correct font mapping |
| Images must be local file paths, not URLs | html2pptx reads from filesystem |
| Content that exceeds 405pt height will overflow — split into multiple slides instead | No scroll in PPT |
| Multi-column equal-width cards: use explicit `width` + `flex-shrink:0`, not `flex:1` | Prevents uneven stretching |
| Titles and short labels: use `white-space:nowrap` | Prevents unexpected line breaks in conversion |
---
## 4. Quick Reference
### Recommended Font Size Range
| Role | Suggested Size | Weight |
|------|---------------|--------|
| Display / decorative number (ghost) | 80100pt | Bold |
| Hero focal metric (single-stat page) | 5688pt | Bold |
| Hero / cover title | 4048pt | Bold |
| KPI dashboard numbers | 3648pt | Bold |
| Section title | 2834pt | Bold |
| Page title (in title bar) | 2630pt | Bold |
| Card / sub heading | 2024pt | Bold |
| Body text | 1416pt | Normal |
| Annotations / footnotes | 1213pt | Normal |
| Captions / tiny labels | 1012pt | Normal |
| Tag / chip label | 1011pt | Normal |
**Ghost number technique**: Large decorative numbers (80100pt) at very low opacity (`color:rgba(255,255,255,0.05)` on dark backgrounds, or `color:rgba(0,0,0,0.04)` on light) add visual depth without competing with readable content. Use as background layer behind chapter numbers, inside TOC cards, or behind section titles.
### Common Spacing Values
| Usage | Suggested |
|-------|-----------|
| Page left/right margins | 48pt |
| Page top margin | 40pt |
| Bottom safe zone | ≥36pt |
| Between heading and body | 8-16pt |
| Between cards | 12-20pt |
| Card internal padding | 16-24pt |
### Width Reference (720pt total)
| Layout | Approximate Column Widths |
|--------|--------------------------|
| Full width (with margins) | ~624pt |
| Two columns | ~296pt each (16pt gap) |
| Three columns | ~192pt each (16pt×2 gaps) |
| Four columns | ~140pt each (16pt×3 gaps) |
### Height Reference (405pt total)
| Component | Approximate Height |
|-----------|--------------------|
| Title bar | ~56pt |
| Single text line (15pt body) | ~23pt |
| KPI number line (40pt) | ~40pt |
| Card padding (top+bottom) | ~32-48pt |
---
**Remember: This system gives you a coherent color palette and a few engine-level constraints. Everything else — layout invention, typography expression, decorative flair, card styling, background artistry — is yours to create freely. Make every slide count.**

394
skills/ppt/html2pptx.md Executable file
View File

@@ -0,0 +1,394 @@
# HTML to PowerPoint Guide
Convert HTML slides into PowerPoint presentations using the `html2pptx.js` library with accurate positioning.
---
## Creating HTML Slides
Each HTML slide must include the correct body dimensions:
### Layout Dimensions
- **16:9** (default): `width: 720pt; height: 405pt`
- **4:3**: `width: 720pt; height: 540pt`
- **16:10**: `width: 720pt; height: 450pt`
**CRITICAL — Prevent Overflow**:
- `<body>` must set exact dimensions via inline style: `width: 720pt; height: 405pt; margin: 0; padding: 0; overflow: hidden;`
- All content must fit within these boundaries. If content overflows, split into multiple slides
- Maintain at least **36pt bottom margin** inside the body for safe spacing
**Fill the slide**: Content should occupy the available space well. Avoid designs where text clusters in the top third with the bottom two-thirds empty. Use generous font sizes, spacing, and visual elements to fill the canvas.
### Supported Elements
- `<p>`, `<h1>`-`<h6>` — Styled text
- `<ul>`, `<ol>` — Lists (never use manual bullet symbols like bullet, -, *)
- `<b>`, `<strong>`, `<i>`, `<em>`, `<u>` — Inline formatting
- `<span>` — Inline formatting with CSS styles
- `<br>` — Line breaks
- `<div>` with bg/border — Becomes shapes
- `<img>` — Images
- `class="placeholder"` — Reserves space for charts (returns `{ id, x, y, w, h }`)
### Key Text Rules
**All text must be inside `<p>`, `<h1>`-`<h6>`, `<ul>`, or `<ol>` tags:**
-`<div><p>Text here</p></div>`
-`<div>Text here</div>`**Silently ignored in PowerPoint**
-`<span>Text here</span>`**Silently ignored in PowerPoint**
**Never use manual bullet symbols (bullet, -, *, etc.)** — use `<ul>` or `<ol>` instead.
**v3 Smart Font Mapping (pass-through + safe fallback):**
html2pptx.js v3 no longer maps all fonts to the same one. Strategy:
1. **PPT-safe fonts** (Corbel, Arial, SimHei, Palatino Linotype, etc. 40+) → **Pass through directly**
2. **macOS-exclusive fonts** (PingFang SC, Hiragino Sans) → Mapped to cross-platform equivalents
3. **Web fonts** (Roboto, Montserrat, Inter, etc. 40+) → Mapped to visually closest PPT-safe font
4. **CSS generic names** (sans-serif/serif) → Corbel / Times New Roman
5. **Unknown fonts** → CJK falls back to fontConfig.cjk; Latin passes through directly
**Write PPT font names directly in HTML**:
```css
font-family: "SimHei", "Microsoft YaHei", sans-serif; /* CJK heading */
font-family: "Microsoft YaHei", sans-serif; /* CJK body */
font-family: "Gill Sans MT", "Century Gothic", sans-serif; /* English heading */
```
**fontConfig is still available** (as CJK/Latin ultimate fallback, optional):
```javascript
const fontConfig = { cjk: 'SimHei', latin: 'Gill Sans MT' };
const result = await html2pptx('slide.html', pptx, { fontConfig });
```
### Styles
- Body must use `display: flex; flex-direction: column;` — without it, multiple direct children stack horizontally
- **Do not use `flex-wrap`** — multi-row layouts must use separate flex containers (html2pptx renderer may lose wrapped content)
- `<span>` supports: `font-weight`, `font-style`, `text-decoration`, `color`, `font-size`, `letter-spacing`; color accepts `rgba()` for transparency
- `<span>` does NOT support: `margin`, `padding`
- `text-transform: uppercase / lowercase / capitalize` works on all text elements and `<span>`
- **Rotated text**: `transform: rotate(-30deg)` or `writing-mode: vertical-rl / vertical-lr`
- Use hex colors with `#` prefix in CSS; use `text-align` for alignment hints
### Shape Styles (DIV elements only)
Backgrounds, borders, and shadows **only work on `<div>`**, not on text elements.
- **Background**: `background-color` on `<div>` only
- **Border**: uniform (`border: 2px solid #333`) or partial (`border-left`, `border-right`, etc.)
- **Border radius**: `border-radius: 8pt` for rounded corners; `50%` for circle; percentages relative to smaller dimension
- **Box shadow**: outer shadows only — `box-shadow: 2px 2px 8px rgba(0,0,0,0.3)`; inset shadows ignored
### Typography Guidelines
Choose font sizes that create clear visual hierarchy. Refer to `design-system.md` for suggested ranges.
**Minimum font size**: Don't go below ~11pt for any text. Prefer ≥13pt for body text.
**Hierarchy principle**: Headings should be noticeably larger and bolder than body text.
### Spacing Guidelines
Use consistent spacing throughout the deck. Refer to `design-system.md` for suggested values. Key principles:
- Page margins: ~48pt left/right, ~40pt top, ≥36pt bottom safe zone
- Be generous with whitespace — but fill the slide; avoid large empty areas
### Color Rules
**All colors must come from the current theme's color scale.** Arbitrary grays unrelated to the primary color are forbidden.
After selecting a theme from `themes.md`, use that theme's complete color scale.
### Image Rules (MANDATORY for decks with 6+ slides)
Every deck with 6+ slides must include real photographs. Images create visual richness and professional quality.
**Image sourcing priority**:
1. **Unsplash** (free, high quality) — use theme's **Image Keywords** from `themes.md`:
```bash
curl -L "https://source.unsplash.com/1920x1080/?keyword1,keyword2" -o cover-bg.jpg
```
2. **User-provided images** — local files
3. **Gradient fallback** — if Unsplash fails, generate gradient PNG via Sharp
**Image usage in HTML**:
- **Page background**: `<body style="background-image:url('bg.jpg'); background-size:cover;">`
- **Inline image**: `<img src="photo.jpg" style="width:296pt; height:220pt; object-fit:cover;">`
- **DIV background-image is NOT supported** — only body background-image works
**Mask overlay for photo backgrounds**:
```html
<!-- Background photo on body -->
<body style="width:720pt; height:405pt; margin:0; padding:0; overflow:hidden;
background-image:url('cover-bg.jpg'); background-size:cover;
font-family:'PingFang SC','Microsoft YaHei',sans-serif;
display:flex; flex-direction:column;">
<!-- Semi-transparent mask layer (use theme's Mask Color from themes.md) -->
<div style="position:absolute; top:0; left:0; width:720pt; height:405pt;
background-color:rgba(18,32,64,0.75);"></div>
<!-- Content layer above mask -->
<div style="position:relative; z-index:1; flex:1; display:flex; flex-direction:column;
justify-content:center; align-items:center;">
<h1 style="font-size:34pt; font-weight:bold; color:#FFFFFF;">Title Here</h1>
</div>
</body>
```
**Mask opacity guide**:
- Dark mask (cover/divider): opacity 0.700.85 — text clearly readable
- Light mask (content): opacity 0.600.80 — retains image visibility
### Icons & Gradients
- **CRITICAL: Never use CSS gradients** — pre-rasterize as PNG with Sharp
- **Icons**: rasterize react-icons SVG to PNG; **Gradients**: rasterize SVG to PNG background
```javascript
// Icon to PNG
const { FaHome } = require('react-icons/fa');
const svgString = ReactDOMServer.renderToStaticMarkup(
React.createElement(FaHome, { color: '#4472C4', size: '256' })
);
await sharp(Buffer.from(svgString)).png().toFile('home-icon.png');
// In HTML: <img src="home-icon.png" style="width:40pt;height:40pt;">
// Gradient to PNG
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="562.5">
<defs><linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#COLOR1"/>
<stop offset="100%" style="stop-color:#COLOR2"/>
</linearGradient></defs>
<rect width="100%" height="100%" fill="url(#g)"/>
</svg>`;
await sharp(Buffer.from(svg)).png().toFile('gradient-bg.png');
// In HTML: <body style="background-image: url('gradient-bg.png');">
```
---
## Using the html2pptx Library
### Dependencies
Globally installed: `pptxgenjs`, `playwright`, `sharp`
### Basic Usage
```javascript
const pptxgen = require('pptxgenjs');
const html2pptx = require('./html2pptx');
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_16x9'; // Must match HTML body dimensions
// Optional: custom font configuration (from themes.md)
const fontConfig = { cjk: 'Microsoft YaHei', latin: 'Gill Sans MT' };
const { slide, placeholders, warnings } = await html2pptx('slide1.html', pptx, { fontConfig });
// If warnings is non-empty, fix the HTML and re-run
if (warnings.length > 0) {
console.error('Fix overflow issues before saving:', warnings);
process.exit(1);
}
if (placeholders.length > 0) {
slide.addChart(pptx.charts.LINE, chartData, placeholders[0]);
}
await pptx.writeFile('output.pptx');
```
### API Reference
```javascript
await html2pptx(htmlFile, pres, options)
```
**Parameters:**
- `htmlFile` (string): Path to HTML file
- `pres` (pptxgen): PptxGenJS instance with layout set
- `options.tmpDir` (string): Temp dir (default: `process.env.TMPDIR || '/tmp'`)
- `options.slide` (object): Existing slide to reuse
- `options.fontConfig` (object): Font mapping config `{ cjk: 'Microsoft YaHei', latin: 'Corbel' }`
**Returns:**
```javascript
{
slide: pptxgenSlide,
placeholders: [{ id, x, y, w, h }, ...],
warnings: string[] // Overflow and layout suggestions; empty if none
}
```
### Validation
**Blocking errors** (conversion aborted):
1. CSS gradients — must be pre-rasterized as PNG
2. Backgrounds/borders/shadows on text elements (`<p>`, `<h1>`-`<h6>`, etc.)
3. Unwrapped text directly in `<div>`
4. Manual bullet symbols in text elements
5. Font size below 11pt
**Non-blocking warnings** (conversion succeeds, returned in `warnings`):
1. Element out of bounds — extends beyond slide edges
2. Vertical imbalance — content clusters in top 55%
3. Text overlap — text elements overlap each other
4. Character density — exceeds 350 CJK / 550 Latin chars
5. Body-level overflow
**Blocking issues** (overflow, font < 11pt) must be fixed. **Non-blocking warnings** are suggestions — use your judgment.
### Visual Quality Check
After generating all slides, do a quick quality scan:
- Is there visual variety across the deck? (different layouts, backgrounds, card styles)
- Do real photographs appear? (at least on cover + 1 other slide for 6+ slide decks)
- Is there at least one dramatic "rhythm breaker" page?
- Does every slide have a clear visual focal point?
### Working with Placeholders
```javascript
const { slide, placeholders } = await html2pptx('slide.html', pptx);
slide.addChart(pptx.charts.BAR, data, placeholders[0]);
// By ID:
const chartArea = placeholders.find(p => p.id === 'chart-area');
slide.addChart(pptx.charts.LINE, data, chartArea);
```
---
## Using PptxGenJS
### Critical Rules
**NEVER use `#` prefix** with hex colors in PptxGenJS — causes file corruption.
- ✅ `color: "FF0000"`, `fill: { color: "0066CC" }`
- ❌ `color: "#FF0000"`
### Adding Images
```javascript
const imgWidth = 1860, imgHeight = 1519;
const h = 3, w = h * (imgWidth / imgHeight);
slide.addImage({ path: "chart.png", x: (10 - w) / 2, y: 1.5, w, h });
```
### Adding Shapes
```javascript
slide.addShape(pptx.shapes.RECTANGLE, {
x: 1, y: 1, w: 3, h: 2,
fill: { color: "4472C4" },
line: { color: "2E5DA8", width: 2 },
rectRadius: 0.1 // rounded corners (ROUNDED_RECTANGLE only)
});
```
### Adding Charts
**Time Series Granularity:** `< 30 days` daily | `30-365 days` monthly | `> 365 days` yearly.
#### Bar Chart
```javascript
slide.addChart(pptx.charts.BAR, [{
name: "Sales 2024",
labels: ["Q1", "Q2", "Q3", "Q4"],
values: [4500, 5500, 6200, 7100]
}], {
...placeholders[0],
barDir: 'col',
showTitle: true, title: 'Quarterly Sales',
showLegend: false,
showCatAxisTitle: true, catAxisTitle: 'Quarter',
showValAxisTitle: true, valAxisTitle: 'Sales ($000s)',
valAxisMinVal: 0, valAxisMaxVal: 8000, valAxisMajorUnit: 2000,
chartColors: ["4472C4"]
});
```
#### Line Chart
```javascript
slide.addChart(pptx.charts.LINE, [{
name: "Temperature",
labels: ["Jan", "Feb", "Mar", "Apr"],
values: [32, 35, 42, 55]
}], {
x: 1, y: 1, w: 8, h: 4,
lineSize: 4, lineSmooth: true,
showCatAxisTitle: true, catAxisTitle: 'Month',
showValAxisTitle: true, valAxisTitle: 'Temp (F)',
valAxisMinVal: 0, valAxisMaxVal: 60, valAxisMajorUnit: 20,
chartColors: ["4472C4"]
});
```
#### Pie Chart
```javascript
slide.addChart(pptx.charts.PIE, [{
name: "Market Share",
labels: ["Product A", "Product B", "Other"],
values: [35, 45, 20]
}], {
x: 2, y: 1, w: 6, h: 4,
showPercent: true, showLegend: true, legendPos: 'r',
chartColors: ["4472C4", "ED7D31", "A5A5A5"]
});
```
#### Scatter Chart
```javascript
slide.addChart(pptx.charts.SCATTER, [
{ name: 'X-Axis', values: [10, 15, 20, 12, 18] },
{ name: 'Series 1', values: [20, 25, 30] },
{ name: 'Series 2', values: [18, 22] }
], {
x: 1, y: 1, w: 8, h: 4,
lineSize: 0, lineDataSymbol: 'circle', lineDataSymbolSize: 6,
showCatAxisTitle: true, catAxisTitle: 'X',
showValAxisTitle: true, valAxisTitle: 'Y',
chartColors: ["4472C4", "ED7D31"]
});
```
#### Multiple Series
```javascript
slide.addChart(pptx.charts.LINE, [
{ name: "Product A", labels: ["Q1","Q2","Q3","Q4"], values: [10,20,30,40] },
{ name: "Product B", labels: ["Q1","Q2","Q3","Q4"], values: [15,25,20,35] }
], { x: 1, y: 1, w: 8, h: 4, showCatAxisTitle: true, catAxisTitle: 'Quarter',
showValAxisTitle: true, valAxisTitle: 'Revenue ($M)' });
```
**Chart colors:** no `#` prefix; align with slide palette; strong contrast between adjacent series.
### Adding Tables
```javascript
const tableData = [
[
{ text: "Product", options: { fill: { color: "4472C4" }, color: "FFFFFF", bold: true } },
{ text: "Revenue", options: { fill: { color: "4472C4" }, color: "FFFFFF", bold: true } },
{ text: "Growth", options: { fill: { color: "4472C4" }, color: "FFFFFF", bold: true } }
],
["Product A", "$50M", "+15%"],
["Product B", "$35M", "+22%"]
];
slide.addTable(tableData, {
x: 1, y: 1.5, w: 8, h: 2.5,
colW: [3, 2.5, 2.5], rowH: [0.5, 0.6, 0.6],
border: { pt: 1, color: "CCCCCC" },
align: "center", valign: "middle", fontSize: 14
});
```
**Table options:** `x, y, w, h` | `colW` | `rowH` | `border: { pt, color }` | `fill` | `align` | `valign` | `fontSize` | `autoPage`

427
skills/ppt/ooxml.md Executable file
View File

@@ -0,0 +1,427 @@
# Office Open XML Technical Reference for PowerPoint
**Important: Read this entire document before starting.** Critical XML schema rules and formatting requirements are covered throughout. Incorrect implementation can create invalid PPTX files that PowerPoint cannot open.
## Technical Guidelines
### Schema Compliance
- **Element ordering in `<p:txBody>`**: `<a:bodyPr>`, `<a:lstStyle>`, `<a:p>`
- **Whitespace**: Add `xml:space='preserve'` to `<a:t>` elements with leading/trailing spaces
- **Unicode**: Escape characters in ASCII content: `"` becomes `&#8220;`
- **Images**: Add to `ppt/media/`, reference in slide XML, set dimensions to fit slide bounds
- **Relationships**: Update `ppt/slides/_rels/slideN.xml.rels` for each slide's resources
- **Dirty attribute**: Add `dirty="0"` to `<a:rPr>` and `<a:endParaRPr>` elements to indicate clean state
## Presentation Structure
### Basic Slide Structure
```xml
<!-- ppt/slides/slide1.xml -->
<p:sld>
<p:cSld>
<p:spTree>
<p:nvGrpSpPr>...</p:nvGrpSpPr>
<p:grpSpPr>...</p:grpSpPr>
<!-- Shapes go here -->
</p:spTree>
</p:cSld>
</p:sld>
```
### Text Box / Shape with Text
```xml
<p:sp>
<p:nvSpPr>
<p:cNvPr id="2" name="Title"/>
<p:cNvSpPr>
<a:spLocks noGrp="1"/>
</p:cNvSpPr>
<p:nvPr>
<p:ph type="ctrTitle"/>
</p:nvPr>
</p:nvSpPr>
<p:spPr>
<a:xfrm>
<a:off x="838200" y="365125"/>
<a:ext cx="7772400" cy="1470025"/>
</a:xfrm>
</p:spPr>
<p:txBody>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:r>
<a:t>Slide Title</a:t>
</a:r>
</a:p>
</p:txBody>
</p:sp>
```
### Text Formatting
```xml
<!-- Bold -->
<a:r>
<a:rPr b="1"/>
<a:t>Bold Text</a:t>
</a:r>
<!-- Italic -->
<a:r>
<a:rPr i="1"/>
<a:t>Italic Text</a:t>
</a:r>
<!-- Underline -->
<a:r>
<a:rPr u="sng"/>
<a:t>Underlined</a:t>
</a:r>
<!-- Highlight -->
<a:r>
<a:rPr>
<a:highlight>
<a:srgbClr val="FFFF00"/>
</a:highlight>
</a:rPr>
<a:t>Highlighted Text</a:t>
</a:r>
<!-- Font and Size -->
<a:r>
<a:rPr sz="2400" typeface="Arial">
<a:solidFill>
<a:srgbClr val="FF0000"/>
</a:solidFill>
</a:rPr>
<a:t>Colored Arial 24pt</a:t>
</a:r>
<!-- Complete formatting example -->
<a:r>
<a:rPr lang="en-US" sz="1400" b="1" dirty="0">
<a:solidFill>
<a:srgbClr val="FAFAFA"/>
</a:solidFill>
</a:rPr>
<a:t>Formatted text</a:t>
</a:r>
```
### Lists
```xml
<!-- Bullet list -->
<a:p>
<a:pPr lvl="0">
<a:buChar char="•"/>
</a:pPr>
<a:r>
<a:t>First bullet point</a:t>
</a:r>
</a:p>
<!-- Numbered list -->
<a:p>
<a:pPr lvl="0">
<a:buAutoNum type="arabicPeriod"/>
</a:pPr>
<a:r>
<a:t>First numbered item</a:t>
</a:r>
</a:p>
<!-- Second level indent -->
<a:p>
<a:pPr lvl="1">
<a:buChar char="•"/>
</a:pPr>
<a:r>
<a:t>Indented bullet</a:t>
</a:r>
</a:p>
```
### Shapes
```xml
<!-- Rectangle -->
<p:sp>
<p:nvSpPr>
<p:cNvPr id="3" name="Rectangle"/>
<p:cNvSpPr/>
<p:nvPr/>
</p:nvSpPr>
<p:spPr>
<a:xfrm>
<a:off x="1000000" y="1000000"/>
<a:ext cx="3000000" cy="2000000"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
<a:solidFill>
<a:srgbClr val="FF0000"/>
</a:solidFill>
<a:ln w="25400">
<a:solidFill>
<a:srgbClr val="000000"/>
</a:solidFill>
</a:ln>
</p:spPr>
</p:sp>
<!-- Rounded Rectangle -->
<p:sp>
<p:spPr>
<a:prstGeom prst="roundRect">
<a:avLst/>
</a:prstGeom>
</p:spPr>
</p:sp>
<!-- Circle/Ellipse -->
<p:sp>
<p:spPr>
<a:prstGeom prst="ellipse">
<a:avLst/>
</a:prstGeom>
</p:spPr>
</p:sp>
```
### Images
```xml
<p:pic>
<p:nvPicPr>
<p:cNvPr id="4" name="Picture">
<a:hlinkClick r:id="" action="ppaction://media"/>
</p:cNvPr>
<p:cNvPicPr>
<a:picLocks noChangeAspect="1"/>
</p:cNvPicPr>
<p:nvPr/>
</p:nvPicPr>
<p:blipFill>
<a:blip r:embed="rId2"/>
<a:stretch>
<a:fillRect/>
</a:stretch>
</p:blipFill>
<p:spPr>
<a:xfrm>
<a:off x="1000000" y="1000000"/>
<a:ext cx="3000000" cy="2000000"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
</p:spPr>
</p:pic>
```
### Tables
```xml
<p:graphicFrame>
<p:nvGraphicFramePr>
<p:cNvPr id="5" name="Table"/>
<p:cNvGraphicFramePr>
<a:graphicFrameLocks noGrp="1"/>
</p:cNvGraphicFramePr>
<p:nvPr/>
</p:nvGraphicFramePr>
<p:xfrm>
<a:off x="1000000" y="1000000"/>
<a:ext cx="6000000" cy="2000000"/>
</p:xfrm>
<a:graphic>
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/table">
<a:tbl>
<a:tblGrid>
<a:gridCol w="3000000"/>
<a:gridCol w="3000000"/>
</a:tblGrid>
<a:tr h="500000">
<a:tc>
<a:txBody>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:r>
<a:t>Cell 1</a:t>
</a:r>
</a:p>
</a:txBody>
</a:tc>
<a:tc>
<a:txBody>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:r>
<a:t>Cell 2</a:t>
</a:r>
</a:p>
</a:txBody>
</a:tc>
</a:tr>
</a:tbl>
</a:graphicData>
</a:graphic>
</p:graphicFrame>
```
### Slide Layouts
```xml
<!-- Title Slide Layout -->
<p:sp>
<p:nvSpPr>
<p:nvPr>
<p:ph type="ctrTitle"/>
</p:nvPr>
</p:nvSpPr>
<!-- Title content -->
</p:sp>
<p:sp>
<p:nvSpPr>
<p:nvPr>
<p:ph type="subTitle" idx="1"/>
</p:nvPr>
</p:nvSpPr>
<!-- Subtitle content -->
</p:sp>
<!-- Content Slide Layout -->
<p:sp>
<p:nvSpPr>
<p:nvPr>
<p:ph type="title"/>
</p:nvPr>
</p:nvSpPr>
<!-- Slide title -->
</p:sp>
<p:sp>
<p:nvSpPr>
<p:nvPr>
<p:ph type="body" idx="1"/>
</p:nvPr>
</p:nvSpPr>
<!-- Content body -->
</p:sp>
```
## File Updates
When adding content, update these files:
**`ppt/_rels/presentation.xml.rels`:**
```xml
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" Target="slides/slide1.xml"/>
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster" Target="slideMasters/slideMaster1.xml"/>
```
**`ppt/slides/_rels/slide1.xml.rels`:**
```xml
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/slideLayout1.xml"/>
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../media/image1.png"/>
```
**`[Content_Types].xml`:**
```xml
<Default Extension="png" ContentType="image/png"/>
<Default Extension="jpg" ContentType="image/jpeg"/>
<Override PartName="/ppt/slides/slide1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/>
```
**`ppt/presentation.xml`:**
```xml
<p:sldIdLst>
<p:sldId id="256" r:id="rId1"/>
<p:sldId id="257" r:id="rId2"/>
</p:sldIdLst>
```
**`docProps/app.xml`:** Update slide count and statistics
```xml
<Slides>2</Slides>
<Paragraphs>10</Paragraphs>
<Words>50</Words>
```
## Slide Operations
### Adding a New Slide
When adding a slide to the end of the presentation:
1. **Create the slide file** (`ppt/slides/slideN.xml`)
2. **Update `[Content_Types].xml`**: Add Override for the new slide
3. **Update `ppt/_rels/presentation.xml.rels`**: Add relationship for the new slide
4. **Update `ppt/presentation.xml`**: Add slide ID to `<p:sldIdLst>`
5. **Create slide relationships** (`ppt/slides/_rels/slideN.xml.rels`) if needed
6. **Update `docProps/app.xml`**: Increment slide count and update statistics (if present)
### Duplicating a Slide
1. Copy the source slide XML file with a new name
2. Update all IDs in the new slide to be unique
3. Follow the "Adding a New Slide" steps above
4. **CRITICAL**: Remove or update any notes slide references in `_rels` files
5. Remove references to unused media files
### Reordering Slides
1. **Update `ppt/presentation.xml`**: Reorder `<p:sldId>` elements in `<p:sldIdLst>`
2. The order of `<p:sldId>` elements determines slide order
3. Keep slide IDs and relationship IDs unchanged
Example:
```xml
<!-- Original order -->
<p:sldIdLst>
<p:sldId id="256" r:id="rId2"/>
<p:sldId id="257" r:id="rId3"/>
<p:sldId id="258" r:id="rId4"/>
</p:sldIdLst>
<!-- After moving slide 3 to position 2 -->
<p:sldIdLst>
<p:sldId id="256" r:id="rId2"/>
<p:sldId id="258" r:id="rId4"/>
<p:sldId id="257" r:id="rId3"/>
</p:sldIdLst>
```
### Deleting a Slide
1. **Remove from `ppt/presentation.xml`**: Delete the `<p:sldId>` entry
2. **Remove from `ppt/_rels/presentation.xml.rels`**: Delete the relationship
3. **Remove from `[Content_Types].xml`**: Delete the Override entry
4. **Delete files**: Remove `ppt/slides/slideN.xml` and `ppt/slides/_rels/slideN.xml.rels`
5. **Update `docProps/app.xml`**: Decrement slide count and update statistics
6. **Clean up unused media**: Remove orphaned images from `ppt/media/`
Note: Don't renumber remaining slides - keep their original IDs and filenames.
## Common Errors to Avoid
- **Encodings**: Escape unicode characters in ASCII content: `"` becomes `&#8220;`
- **Images**: Add to `ppt/media/` and update relationship files
- **Lists**: Omit bullets from list headers
- **IDs**: Use valid hexadecimal values for UUIDs
- **Themes**: Check all themes in `theme` directory for colors
## Validation Checklist for Template-Based Presentations
### Before Packing, Always:
- **Clean unused resources**: Remove unreferenced media, fonts, and notes directories
- **Fix Content_Types.xml**: Declare ALL slides, layouts, and themes present in the package
- **Fix relationship IDs**:
- Remove font embed references if not using embedded fonts
- **Remove broken references**: Check all `_rels` files for references to deleted resources
### Common Template Duplication Pitfalls:
- Multiple slides referencing the same notes slide after duplication
- Image/media references from template slides that no longer exist
- Font embedding references when fonts aren't included
- Missing slideLayout declarations for layouts 12-25
- docProps directory may not unpack - this is optional

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing"
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing"
elementFormDefault="qualified">
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
schemaLocation="dml-main.xsd"/>
<xsd:complexType name="CT_ShapeNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvSpPr" type="a:CT_NonVisualDrawingShapeProps" minOccurs="1" maxOccurs="1"
/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Shape">
<xsd:sequence>
<xsd:element name="nvSpPr" type="CT_ShapeNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
<xsd:element name="txBody" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
<xsd:attribute name="textlink" type="xsd:string" use="optional"/>
<xsd:attribute name="fLocksText" type="xsd:boolean" use="optional" default="true"/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_ConnectorNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvCxnSpPr" type="a:CT_NonVisualConnectorProperties" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Connector">
<xsd:sequence>
<xsd:element name="nvCxnSpPr" type="CT_ConnectorNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_PictureNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvPicPr" type="a:CT_NonVisualPictureProperties" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Picture">
<xsd:sequence>
<xsd:element name="nvPicPr" type="CT_PictureNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="blipFill" type="a:CT_BlipFillProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_GraphicFrameNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GraphicFrame">
<xsd:sequence>
<xsd:element name="nvGraphicFramePr" type="CT_GraphicFrameNonVisual" minOccurs="1"
maxOccurs="1"/>
<xsd:element name="xfrm" type="a:CT_Transform2D" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_GroupShapeNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvGrpSpPr" type="a:CT_NonVisualGroupDrawingShapeProps" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GroupShape">
<xsd:sequence>
<xsd:element name="nvGrpSpPr" type="CT_GroupShapeNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="grpSpPr" type="a:CT_GroupShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="sp" type="CT_Shape"/>
<xsd:element name="grpSp" type="CT_GroupShape"/>
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
<xsd:element name="cxnSp" type="CT_Connector"/>
<xsd:element name="pic" type="CT_Picture"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_ObjectChoices">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="sp" type="CT_Shape"/>
<xsd:element name="grpSp" type="CT_GroupShape"/>
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
<xsd:element name="cxnSp" type="CT_Connector"/>
<xsd:element name="pic" type="CT_Picture"/>
</xsd:choice>
</xsd:sequence>
</xsd:group>
<xsd:simpleType name="ST_MarkerCoordinate">
<xsd:restriction base="xsd:double">
<xsd:minInclusive value="0.0"/>
<xsd:maxInclusive value="1.0"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Marker">
<xsd:sequence>
<xsd:element name="x" type="ST_MarkerCoordinate" minOccurs="1" maxOccurs="1"/>
<xsd:element name="y" type="ST_MarkerCoordinate" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_RelSizeAnchor">
<xsd:sequence>
<xsd:element name="from" type="CT_Marker"/>
<xsd:element name="to" type="CT_Marker"/>
<xsd:group ref="EG_ObjectChoices"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_AbsSizeAnchor">
<xsd:sequence>
<xsd:element name="from" type="CT_Marker"/>
<xsd:element name="ext" type="a:CT_PositiveSize2D"/>
<xsd:group ref="EG_ObjectChoices"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_Anchor">
<xsd:choice>
<xsd:element name="relSizeAnchor" type="CT_RelSizeAnchor"/>
<xsd:element name="absSizeAnchor" type="CT_AbsSizeAnchor"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_Drawing">
<xsd:sequence>
<xsd:group ref="EG_Anchor" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
elementFormDefault="qualified"
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas">
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
schemaLocation="dml-main.xsd"/>
<xsd:element name="lockedCanvas" type="a:CT_GvmlGroupShape"/>
</xsd:schema>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/drawingml/2006/picture"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" elementFormDefault="qualified"
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/picture">
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
schemaLocation="dml-main.xsd"/>
<xsd:complexType name="CT_PictureNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvPicPr" type="a:CT_NonVisualPictureProperties" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Picture">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element name="nvPicPr" type="CT_PictureNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="blipFill" type="a:CT_BlipFillProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="pic" type="CT_Picture"/>
</xsd:schema>

View File

@@ -0,0 +1,185 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
elementFormDefault="qualified">
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
schemaLocation="dml-main.xsd"/>
<xsd:import schemaLocation="shared-relationshipReference.xsd"
namespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships"/>
<xsd:element name="from" type="CT_Marker"/>
<xsd:element name="to" type="CT_Marker"/>
<xsd:complexType name="CT_AnchorClientData">
<xsd:attribute name="fLocksWithSheet" type="xsd:boolean" use="optional" default="true"/>
<xsd:attribute name="fPrintsWithSheet" type="xsd:boolean" use="optional" default="true"/>
</xsd:complexType>
<xsd:complexType name="CT_ShapeNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvSpPr" type="a:CT_NonVisualDrawingShapeProps" minOccurs="1" maxOccurs="1"
/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Shape">
<xsd:sequence>
<xsd:element name="nvSpPr" type="CT_ShapeNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
<xsd:element name="txBody" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
<xsd:attribute name="textlink" type="xsd:string" use="optional"/>
<xsd:attribute name="fLocksText" type="xsd:boolean" use="optional" default="true"/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_ConnectorNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvCxnSpPr" type="a:CT_NonVisualConnectorProperties" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Connector">
<xsd:sequence>
<xsd:element name="nvCxnSpPr" type="CT_ConnectorNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_PictureNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvPicPr" type="a:CT_NonVisualPictureProperties" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Picture">
<xsd:sequence>
<xsd:element name="nvPicPr" type="CT_PictureNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="blipFill" type="a:CT_BlipFillProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_GraphicalObjectFrameNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GraphicalObjectFrame">
<xsd:sequence>
<xsd:element name="nvGraphicFramePr" type="CT_GraphicalObjectFrameNonVisual" minOccurs="1"
maxOccurs="1"/>
<xsd:element name="xfrm" type="a:CT_Transform2D" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_GroupShapeNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvGrpSpPr" type="a:CT_NonVisualGroupDrawingShapeProps" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GroupShape">
<xsd:sequence>
<xsd:element name="nvGrpSpPr" type="CT_GroupShapeNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="grpSpPr" type="a:CT_GroupShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="sp" type="CT_Shape"/>
<xsd:element name="grpSp" type="CT_GroupShape"/>
<xsd:element name="graphicFrame" type="CT_GraphicalObjectFrame"/>
<xsd:element name="cxnSp" type="CT_Connector"/>
<xsd:element name="pic" type="CT_Picture"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_ObjectChoices">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="sp" type="CT_Shape"/>
<xsd:element name="grpSp" type="CT_GroupShape"/>
<xsd:element name="graphicFrame" type="CT_GraphicalObjectFrame"/>
<xsd:element name="cxnSp" type="CT_Connector"/>
<xsd:element name="pic" type="CT_Picture"/>
<xsd:element name="contentPart" type="CT_Rel"/>
</xsd:choice>
</xsd:sequence>
</xsd:group>
<xsd:complexType name="CT_Rel">
<xsd:attribute ref="r:id" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_ColID">
<xsd:restriction base="xsd:int">
<xsd:minInclusive value="0"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_RowID">
<xsd:restriction base="xsd:int">
<xsd:minInclusive value="0"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Marker">
<xsd:sequence>
<xsd:element name="col" type="ST_ColID"/>
<xsd:element name="colOff" type="a:ST_Coordinate"/>
<xsd:element name="row" type="ST_RowID"/>
<xsd:element name="rowOff" type="a:ST_Coordinate"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="ST_EditAs">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="twoCell"/>
<xsd:enumeration value="oneCell"/>
<xsd:enumeration value="absolute"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_TwoCellAnchor">
<xsd:sequence>
<xsd:element name="from" type="CT_Marker"/>
<xsd:element name="to" type="CT_Marker"/>
<xsd:group ref="EG_ObjectChoices"/>
<xsd:element name="clientData" type="CT_AnchorClientData" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="editAs" type="ST_EditAs" use="optional" default="twoCell"/>
</xsd:complexType>
<xsd:complexType name="CT_OneCellAnchor">
<xsd:sequence>
<xsd:element name="from" type="CT_Marker"/>
<xsd:element name="ext" type="a:CT_PositiveSize2D"/>
<xsd:group ref="EG_ObjectChoices"/>
<xsd:element name="clientData" type="CT_AnchorClientData" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_AbsoluteAnchor">
<xsd:sequence>
<xsd:element name="pos" type="a:CT_Point2D"/>
<xsd:element name="ext" type="a:CT_PositiveSize2D"/>
<xsd:group ref="EG_ObjectChoices"/>
<xsd:element name="clientData" type="CT_AnchorClientData" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_Anchor">
<xsd:choice>
<xsd:element name="twoCellAnchor" type="CT_TwoCellAnchor"/>
<xsd:element name="oneCellAnchor" type="CT_OneCellAnchor"/>
<xsd:element name="absoluteAnchor" type="CT_AbsoluteAnchor"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_Drawing">
<xsd:sequence>
<xsd:group ref="EG_Anchor" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="wsDr" type="CT_Drawing"/>
</xsd:schema>

View File

@@ -0,0 +1,287 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:dpct="http://schemas.openxmlformats.org/drawingml/2006/picture"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
elementFormDefault="qualified">
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
schemaLocation="dml-main.xsd"/>
<xsd:import schemaLocation="wml.xsd"
namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main"/>
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/picture"
schemaLocation="dml-picture.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
schemaLocation="shared-relationshipReference.xsd"/>
<xsd:complexType name="CT_EffectExtent">
<xsd:attribute name="l" type="a:ST_Coordinate" use="required"/>
<xsd:attribute name="t" type="a:ST_Coordinate" use="required"/>
<xsd:attribute name="r" type="a:ST_Coordinate" use="required"/>
<xsd:attribute name="b" type="a:ST_Coordinate" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_WrapDistance">
<xsd:restriction base="xsd:unsignedInt"/>
</xsd:simpleType>
<xsd:complexType name="CT_Inline">
<xsd:sequence>
<xsd:element name="extent" type="a:CT_PositiveSize2D"/>
<xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
<xsd:element name="docPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
minOccurs="0" maxOccurs="1"/>
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
</xsd:complexType>
<xsd:simpleType name="ST_WrapText">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="bothSides"/>
<xsd:enumeration value="left"/>
<xsd:enumeration value="right"/>
<xsd:enumeration value="largest"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_WrapPath">
<xsd:sequence>
<xsd:element name="start" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/>
<xsd:element name="lineTo" type="a:CT_Point2D" minOccurs="2" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="edited" type="xsd:boolean" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_WrapNone"/>
<xsd:complexType name="CT_WrapSquare">
<xsd:sequence>
<xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
<xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_WrapTight">
<xsd:sequence>
<xsd:element name="wrapPolygon" type="CT_WrapPath" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_WrapThrough">
<xsd:sequence>
<xsd:element name="wrapPolygon" type="CT_WrapPath" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_WrapTopBottom">
<xsd:sequence>
<xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
</xsd:complexType>
<xsd:group name="EG_WrapType">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="wrapNone" type="CT_WrapNone" minOccurs="1" maxOccurs="1"/>
<xsd:element name="wrapSquare" type="CT_WrapSquare" minOccurs="1" maxOccurs="1"/>
<xsd:element name="wrapTight" type="CT_WrapTight" minOccurs="1" maxOccurs="1"/>
<xsd:element name="wrapThrough" type="CT_WrapThrough" minOccurs="1" maxOccurs="1"/>
<xsd:element name="wrapTopAndBottom" type="CT_WrapTopBottom" minOccurs="1" maxOccurs="1"/>
</xsd:choice>
</xsd:sequence>
</xsd:group>
<xsd:simpleType name="ST_PositionOffset">
<xsd:restriction base="xsd:int"/>
</xsd:simpleType>
<xsd:simpleType name="ST_AlignH">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="left"/>
<xsd:enumeration value="right"/>
<xsd:enumeration value="center"/>
<xsd:enumeration value="inside"/>
<xsd:enumeration value="outside"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_RelFromH">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="margin"/>
<xsd:enumeration value="page"/>
<xsd:enumeration value="column"/>
<xsd:enumeration value="character"/>
<xsd:enumeration value="leftMargin"/>
<xsd:enumeration value="rightMargin"/>
<xsd:enumeration value="insideMargin"/>
<xsd:enumeration value="outsideMargin"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_PosH">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="align" type="ST_AlignH" minOccurs="1" maxOccurs="1"/>
<xsd:element name="posOffset" type="ST_PositionOffset" minOccurs="1" maxOccurs="1"/>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="relativeFrom" type="ST_RelFromH" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_AlignV">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="top"/>
<xsd:enumeration value="bottom"/>
<xsd:enumeration value="center"/>
<xsd:enumeration value="inside"/>
<xsd:enumeration value="outside"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_RelFromV">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="margin"/>
<xsd:enumeration value="page"/>
<xsd:enumeration value="paragraph"/>
<xsd:enumeration value="line"/>
<xsd:enumeration value="topMargin"/>
<xsd:enumeration value="bottomMargin"/>
<xsd:enumeration value="insideMargin"/>
<xsd:enumeration value="outsideMargin"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_PosV">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="align" type="ST_AlignV" minOccurs="1" maxOccurs="1"/>
<xsd:element name="posOffset" type="ST_PositionOffset" minOccurs="1" maxOccurs="1"/>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="relativeFrom" type="ST_RelFromV" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Anchor">
<xsd:sequence>
<xsd:element name="simplePos" type="a:CT_Point2D"/>
<xsd:element name="positionH" type="CT_PosH"/>
<xsd:element name="positionV" type="CT_PosV"/>
<xsd:element name="extent" type="a:CT_PositiveSize2D"/>
<xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
<xsd:group ref="EG_WrapType"/>
<xsd:element name="docPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
minOccurs="0" maxOccurs="1"/>
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="simplePos" type="xsd:boolean"/>
<xsd:attribute name="relativeHeight" type="xsd:unsignedInt" use="required"/>
<xsd:attribute name="behindDoc" type="xsd:boolean" use="required"/>
<xsd:attribute name="locked" type="xsd:boolean" use="required"/>
<xsd:attribute name="layoutInCell" type="xsd:boolean" use="required"/>
<xsd:attribute name="hidden" type="xsd:boolean" use="optional"/>
<xsd:attribute name="allowOverlap" type="xsd:boolean" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_TxbxContent">
<xsd:group ref="w:EG_BlockLevelElts" minOccurs="1" maxOccurs="unbounded"/>
</xsd:complexType>
<xsd:complexType name="CT_TextboxInfo">
<xsd:sequence>
<xsd:element name="txbxContent" type="CT_TxbxContent" minOccurs="1" maxOccurs="1"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:unsignedShort" use="optional" default="0"/>
</xsd:complexType>
<xsd:complexType name="CT_LinkedTextboxInformation">
<xsd:sequence>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:unsignedShort" use="required"/>
<xsd:attribute name="seq" type="xsd:unsignedShort" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_WordprocessingShape">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="0" maxOccurs="1"/>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="cNvSpPr" type="a:CT_NonVisualDrawingShapeProps" minOccurs="1"
maxOccurs="1"/>
<xsd:element name="cNvCnPr" type="a:CT_NonVisualConnectorProperties" minOccurs="1"
maxOccurs="1"/>
</xsd:choice>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
<xsd:choice minOccurs="0" maxOccurs="1">
<xsd:element name="txbx" type="CT_TextboxInfo" minOccurs="1" maxOccurs="1"/>
<xsd:element name="linkedTxbx" type="CT_LinkedTextboxInformation" minOccurs="1"
maxOccurs="1"/>
</xsd:choice>
<xsd:element name="bodyPr" type="a:CT_TextBodyProperties" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="normalEastAsianFlow" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_GraphicFrame">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvFrPr" type="a:CT_NonVisualGraphicFrameProperties" minOccurs="1"
maxOccurs="1"/>
<xsd:element name="xfrm" type="a:CT_Transform2D" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_WordprocessingContentPartNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="0" maxOccurs="1"/>
<xsd:element name="cNvContentPartPr" type="a:CT_NonVisualContentPartProperties" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_WordprocessingContentPart">
<xsd:sequence>
<xsd:element name="nvContentPartPr" type="CT_WordprocessingContentPartNonVisual" minOccurs="0" maxOccurs="1"/>
<xsd:element name="xfrm" type="a:CT_Transform2D" minOccurs="0" maxOccurs="1"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="bwMode" type="a:ST_BlackWhiteMode" use="optional"/>
<xsd:attribute ref="r:id" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_WordprocessingGroup">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="0" maxOccurs="1"/>
<xsd:element name="cNvGrpSpPr" type="a:CT_NonVisualGroupDrawingShapeProps" minOccurs="1"
maxOccurs="1"/>
<xsd:element name="grpSpPr" type="a:CT_GroupShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="wsp"/>
<xsd:element name="grpSp" type="CT_WordprocessingGroup"/>
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
<xsd:element ref="dpct:pic"/>
<xsd:element name="contentPart" type="CT_WordprocessingContentPart"/>
</xsd:choice>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_WordprocessingCanvas">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element name="bg" type="a:CT_BackgroundFormatting" minOccurs="0" maxOccurs="1"/>
<xsd:element name="whole" type="a:CT_WholeE2oFormatting" minOccurs="0" maxOccurs="1"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="wsp"/>
<xsd:element ref="dpct:pic"/>
<xsd:element name="contentPart" type="CT_WordprocessingContentPart"/>
<xsd:element ref="wgp"/>
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
</xsd:choice>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="wpc" type="CT_WordprocessingCanvas"/>
<xsd:element name="wgp" type="CT_WordprocessingGroup"/>
<xsd:element name="wsp" type="CT_WordprocessingShape"/>
<xsd:element name="inline" type="CT_Inline"/>
<xsd:element name="anchor" type="CT_Anchor"/>
</xsd:schema>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/characteristics"
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/characteristics"
elementFormDefault="qualified">
<xsd:complexType name="CT_AdditionalCharacteristics">
<xsd:sequence>
<xsd:element name="characteristic" type="CT_Characteristic" minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Characteristic">
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="relation" type="ST_Relation" use="required"/>
<xsd:attribute name="val" type="xsd:string" use="required"/>
<xsd:attribute name="vocabulary" type="xsd:anyURI" use="optional"/>
</xsd:complexType>
<xsd:simpleType name="ST_Relation">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="ge"/>
<xsd:enumeration value="le"/>
<xsd:enumeration value="gt"/>
<xsd:enumeration value="lt"/>
<xsd:enumeration value="eq"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="additionalCharacteristics" type="CT_AdditionalCharacteristics"/>
</xsd:schema>

View File

@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/bibliography"
xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/bibliography"
elementFormDefault="qualified">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
schemaLocation="shared-commonSimpleTypes.xsd"/>
<xsd:simpleType name="ST_SourceType">
<xsd:restriction base="s:ST_String">
<xsd:enumeration value="ArticleInAPeriodical"/>
<xsd:enumeration value="Book"/>
<xsd:enumeration value="BookSection"/>
<xsd:enumeration value="JournalArticle"/>
<xsd:enumeration value="ConferenceProceedings"/>
<xsd:enumeration value="Report"/>
<xsd:enumeration value="SoundRecording"/>
<xsd:enumeration value="Performance"/>
<xsd:enumeration value="Art"/>
<xsd:enumeration value="DocumentFromInternetSite"/>
<xsd:enumeration value="InternetSite"/>
<xsd:enumeration value="Film"/>
<xsd:enumeration value="Interview"/>
<xsd:enumeration value="Patent"/>
<xsd:enumeration value="ElectronicSource"/>
<xsd:enumeration value="Case"/>
<xsd:enumeration value="Misc"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_NameListType">
<xsd:sequence>
<xsd:element name="Person" type="CT_PersonType" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_PersonType">
<xsd:sequence>
<xsd:element name="Last" type="s:ST_String" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="First" type="s:ST_String" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Middle" type="s:ST_String" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NameType">
<xsd:sequence>
<xsd:element name="NameList" type="CT_NameListType" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NameOrCorporateType">
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="1">
<xsd:element name="NameList" type="CT_NameListType" minOccurs="1" maxOccurs="1"/>
<xsd:element name="Corporate" minOccurs="1" maxOccurs="1" type="s:ST_String"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_AuthorType">
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="Artist" type="CT_NameType"/>
<xsd:element name="Author" type="CT_NameOrCorporateType"/>
<xsd:element name="BookAuthor" type="CT_NameType"/>
<xsd:element name="Compiler" type="CT_NameType"/>
<xsd:element name="Composer" type="CT_NameType"/>
<xsd:element name="Conductor" type="CT_NameType"/>
<xsd:element name="Counsel" type="CT_NameType"/>
<xsd:element name="Director" type="CT_NameType"/>
<xsd:element name="Editor" type="CT_NameType"/>
<xsd:element name="Interviewee" type="CT_NameType"/>
<xsd:element name="Interviewer" type="CT_NameType"/>
<xsd:element name="Inventor" type="CT_NameType"/>
<xsd:element name="Performer" type="CT_NameOrCorporateType"/>
<xsd:element name="ProducerName" type="CT_NameType"/>
<xsd:element name="Translator" type="CT_NameType"/>
<xsd:element name="Writer" type="CT_NameType"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SourceType">
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="AbbreviatedCaseNumber" type="s:ST_String"/>
<xsd:element name="AlbumTitle" type="s:ST_String"/>
<xsd:element name="Author" type="CT_AuthorType"/>
<xsd:element name="BookTitle" type="s:ST_String"/>
<xsd:element name="Broadcaster" type="s:ST_String"/>
<xsd:element name="BroadcastTitle" type="s:ST_String"/>
<xsd:element name="CaseNumber" type="s:ST_String"/>
<xsd:element name="ChapterNumber" type="s:ST_String"/>
<xsd:element name="City" type="s:ST_String"/>
<xsd:element name="Comments" type="s:ST_String"/>
<xsd:element name="ConferenceName" type="s:ST_String"/>
<xsd:element name="CountryRegion" type="s:ST_String"/>
<xsd:element name="Court" type="s:ST_String"/>
<xsd:element name="Day" type="s:ST_String"/>
<xsd:element name="DayAccessed" type="s:ST_String"/>
<xsd:element name="Department" type="s:ST_String"/>
<xsd:element name="Distributor" type="s:ST_String"/>
<xsd:element name="Edition" type="s:ST_String"/>
<xsd:element name="Guid" type="s:ST_String"/>
<xsd:element name="Institution" type="s:ST_String"/>
<xsd:element name="InternetSiteTitle" type="s:ST_String"/>
<xsd:element name="Issue" type="s:ST_String"/>
<xsd:element name="JournalName" type="s:ST_String"/>
<xsd:element name="LCID" type="s:ST_Lang"/>
<xsd:element name="Medium" type="s:ST_String"/>
<xsd:element name="Month" type="s:ST_String"/>
<xsd:element name="MonthAccessed" type="s:ST_String"/>
<xsd:element name="NumberVolumes" type="s:ST_String"/>
<xsd:element name="Pages" type="s:ST_String"/>
<xsd:element name="PatentNumber" type="s:ST_String"/>
<xsd:element name="PeriodicalTitle" type="s:ST_String"/>
<xsd:element name="ProductionCompany" type="s:ST_String"/>
<xsd:element name="PublicationTitle" type="s:ST_String"/>
<xsd:element name="Publisher" type="s:ST_String"/>
<xsd:element name="RecordingNumber" type="s:ST_String"/>
<xsd:element name="RefOrder" type="s:ST_String"/>
<xsd:element name="Reporter" type="s:ST_String"/>
<xsd:element name="SourceType" type="ST_SourceType"/>
<xsd:element name="ShortTitle" type="s:ST_String"/>
<xsd:element name="StandardNumber" type="s:ST_String"/>
<xsd:element name="StateProvince" type="s:ST_String"/>
<xsd:element name="Station" type="s:ST_String"/>
<xsd:element name="Tag" type="s:ST_String"/>
<xsd:element name="Theater" type="s:ST_String"/>
<xsd:element name="ThesisType" type="s:ST_String"/>
<xsd:element name="Title" type="s:ST_String"/>
<xsd:element name="Type" type="s:ST_String"/>
<xsd:element name="URL" type="s:ST_String"/>
<xsd:element name="Version" type="s:ST_String"/>
<xsd:element name="Volume" type="s:ST_String"/>
<xsd:element name="Year" type="s:ST_String"/>
<xsd:element name="YearAccessed" type="s:ST_String"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="Sources" type="CT_Sources"/>
<xsd:complexType name="CT_Sources">
<xsd:sequence>
<xsd:element name="Source" type="CT_SourceType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="SelectedStyle" type="s:ST_String"/>
<xsd:attribute name="StyleName" type="s:ST_String"/>
<xsd:attribute name="URI" type="s:ST_String"/>
</xsd:complexType>
</xsd:schema>

View File

@@ -0,0 +1,174 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
elementFormDefault="qualified">
<xsd:simpleType name="ST_Lang">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="ST_HexColorRGB">
<xsd:restriction base="xsd:hexBinary">
<xsd:length value="3" fixed="true"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Panose">
<xsd:restriction base="xsd:hexBinary">
<xsd:length value="10"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_CalendarType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="gregorian"/>
<xsd:enumeration value="gregorianUs"/>
<xsd:enumeration value="gregorianMeFrench"/>
<xsd:enumeration value="gregorianArabic"/>
<xsd:enumeration value="hijri"/>
<xsd:enumeration value="hebrew"/>
<xsd:enumeration value="taiwan"/>
<xsd:enumeration value="japan"/>
<xsd:enumeration value="thai"/>
<xsd:enumeration value="korea"/>
<xsd:enumeration value="saka"/>
<xsd:enumeration value="gregorianXlitEnglish"/>
<xsd:enumeration value="gregorianXlitFrench"/>
<xsd:enumeration value="none"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_AlgClass">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="hash"/>
<xsd:enumeration value="custom"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_CryptProv">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="rsaAES"/>
<xsd:enumeration value="rsaFull"/>
<xsd:enumeration value="custom"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_AlgType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="typeAny"/>
<xsd:enumeration value="custom"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ColorType">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="ST_Guid">
<xsd:restriction base="xsd:token">
<xsd:pattern value="\{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_OnOff">
<xsd:union memberTypes="xsd:boolean ST_OnOff1"/>
</xsd:simpleType>
<xsd:simpleType name="ST_OnOff1">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="on"/>
<xsd:enumeration value="off"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_String">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="ST_XmlName">
<xsd:restriction base="xsd:NCName">
<xsd:minLength value="1"/>
<xsd:maxLength value="255"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TrueFalse">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="t"/>
<xsd:enumeration value="f"/>
<xsd:enumeration value="true"/>
<xsd:enumeration value="false"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TrueFalseBlank">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="t"/>
<xsd:enumeration value="f"/>
<xsd:enumeration value="true"/>
<xsd:enumeration value="false"/>
<xsd:enumeration value=""/>
<xsd:enumeration value="True"/>
<xsd:enumeration value="False"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_UnsignedDecimalNumber">
<xsd:restriction base="xsd:decimal">
<xsd:minInclusive value="0"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TwipsMeasure">
<xsd:union memberTypes="ST_UnsignedDecimalNumber ST_PositiveUniversalMeasure"/>
</xsd:simpleType>
<xsd:simpleType name="ST_VerticalAlignRun">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="baseline"/>
<xsd:enumeration value="superscript"/>
<xsd:enumeration value="subscript"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Xstring">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="ST_XAlign">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="left"/>
<xsd:enumeration value="center"/>
<xsd:enumeration value="right"/>
<xsd:enumeration value="inside"/>
<xsd:enumeration value="outside"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_YAlign">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="inline"/>
<xsd:enumeration value="top"/>
<xsd:enumeration value="center"/>
<xsd:enumeration value="bottom"/>
<xsd:enumeration value="inside"/>
<xsd:enumeration value="outside"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ConformanceClass">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="strict"/>
<xsd:enumeration value="transitional"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_UniversalMeasure">
<xsd:restriction base="xsd:string">
<xsd:pattern value="-?[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_PositiveUniversalMeasure">
<xsd:restriction base="ST_UniversalMeasure">
<xsd:pattern value="[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Percentage">
<xsd:restriction base="xsd:string">
<xsd:pattern value="-?[0-9]+(\.[0-9]+)?%"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_FixedPercentage">
<xsd:restriction base="ST_Percentage">
<xsd:pattern value="-?((100)|([0-9][0-9]?))(\.[0-9][0-9]?)?%"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_PositivePercentage">
<xsd:restriction base="ST_Percentage">
<xsd:pattern value="[0-9]+(\.[0-9]+)?%"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_PositiveFixedPercentage">
<xsd:restriction base="ST_Percentage">
<xsd:pattern value="((100)|([0-9][0-9]?))(\.[0-9][0-9]?)?%"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/customXml"
xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/customXml"
elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
schemaLocation="shared-commonSimpleTypes.xsd"/>
<xsd:complexType name="CT_DatastoreSchemaRef">
<xsd:attribute name="uri" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_DatastoreSchemaRefs">
<xsd:sequence>
<xsd:element name="schemaRef" type="CT_DatastoreSchemaRef" minOccurs="0" maxOccurs="unbounded"
/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_DatastoreItem">
<xsd:sequence>
<xsd:element name="schemaRefs" type="CT_DatastoreSchemaRefs" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="itemID" type="s:ST_Guid" use="required"/>
</xsd:complexType>
<xsd:element name="datastoreItem" type="CT_DatastoreItem"/>
</xsd:schema>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/schemaLibrary/2006/main"
targetNamespace="http://schemas.openxmlformats.org/schemaLibrary/2006/main"
attributeFormDefault="qualified" elementFormDefault="qualified">
<xsd:complexType name="CT_Schema">
<xsd:attribute name="uri" type="xsd:string" default=""/>
<xsd:attribute name="manifestLocation" type="xsd:string"/>
<xsd:attribute name="schemaLocation" type="xsd:string"/>
<xsd:attribute name="schemaLanguage" type="xsd:token"/>
</xsd:complexType>
<xsd:complexType name="CT_SchemaLibrary">
<xsd:sequence>
<xsd:element name="schema" type="CT_Schema" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="schemaLibrary" type="CT_SchemaLibrary"/>
</xsd:schema>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"
xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"
xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"
blockDefault="#all" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"
schemaLocation="shared-documentPropertiesVariantTypes.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
schemaLocation="shared-commonSimpleTypes.xsd"/>
<xsd:element name="Properties" type="CT_Properties"/>
<xsd:complexType name="CT_Properties">
<xsd:sequence>
<xsd:element name="property" minOccurs="0" maxOccurs="unbounded" type="CT_Property"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Property">
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element ref="vt:vector"/>
<xsd:element ref="vt:array"/>
<xsd:element ref="vt:blob"/>
<xsd:element ref="vt:oblob"/>
<xsd:element ref="vt:empty"/>
<xsd:element ref="vt:null"/>
<xsd:element ref="vt:i1"/>
<xsd:element ref="vt:i2"/>
<xsd:element ref="vt:i4"/>
<xsd:element ref="vt:i8"/>
<xsd:element ref="vt:int"/>
<xsd:element ref="vt:ui1"/>
<xsd:element ref="vt:ui2"/>
<xsd:element ref="vt:ui4"/>
<xsd:element ref="vt:ui8"/>
<xsd:element ref="vt:uint"/>
<xsd:element ref="vt:r4"/>
<xsd:element ref="vt:r8"/>
<xsd:element ref="vt:decimal"/>
<xsd:element ref="vt:lpstr"/>
<xsd:element ref="vt:lpwstr"/>
<xsd:element ref="vt:bstr"/>
<xsd:element ref="vt:date"/>
<xsd:element ref="vt:filetime"/>
<xsd:element ref="vt:bool"/>
<xsd:element ref="vt:cy"/>
<xsd:element ref="vt:error"/>
<xsd:element ref="vt:stream"/>
<xsd:element ref="vt:ostream"/>
<xsd:element ref="vt:storage"/>
<xsd:element ref="vt:ostorage"/>
<xsd:element ref="vt:vstream"/>
<xsd:element ref="vt:clsid"/>
</xsd:choice>
<xsd:attribute name="fmtid" use="required" type="s:ST_Guid"/>
<xsd:attribute name="pid" use="required" type="xsd:int"/>
<xsd:attribute name="name" use="optional" type="xsd:string"/>
<xsd:attribute name="linkTarget" use="optional" type="xsd:string"/>
</xsd:complexType>
</xsd:schema>

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"
xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"
elementFormDefault="qualified" blockDefault="#all">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"
schemaLocation="shared-documentPropertiesVariantTypes.xsd"/>
<xsd:element name="Properties" type="CT_Properties"/>
<xsd:complexType name="CT_Properties">
<xsd:all>
<xsd:element name="Template" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element name="Manager" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element name="Company" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element name="Pages" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="Words" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="Characters" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="PresentationFormat" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element name="Lines" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="Paragraphs" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="Slides" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="Notes" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="TotalTime" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="HiddenSlides" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="MMClips" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="ScaleCrop" minOccurs="0" maxOccurs="1" type="xsd:boolean"/>
<xsd:element name="HeadingPairs" minOccurs="0" maxOccurs="1" type="CT_VectorVariant"/>
<xsd:element name="TitlesOfParts" minOccurs="0" maxOccurs="1" type="CT_VectorLpstr"/>
<xsd:element name="LinksUpToDate" minOccurs="0" maxOccurs="1" type="xsd:boolean"/>
<xsd:element name="CharactersWithSpaces" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="SharedDoc" minOccurs="0" maxOccurs="1" type="xsd:boolean"/>
<xsd:element name="HyperlinkBase" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element name="HLinks" minOccurs="0" maxOccurs="1" type="CT_VectorVariant"/>
<xsd:element name="HyperlinksChanged" minOccurs="0" maxOccurs="1" type="xsd:boolean"/>
<xsd:element name="DigSig" minOccurs="0" maxOccurs="1" type="CT_DigSigBlob"/>
<xsd:element name="Application" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element name="AppVersion" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element name="DocSecurity" minOccurs="0" maxOccurs="1" type="xsd:int"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="CT_VectorVariant">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element ref="vt:vector"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_VectorLpstr">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element ref="vt:vector"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_DigSigBlob">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element ref="vt:blob"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

View File

@@ -0,0 +1,195 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"
xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"
blockDefault="#all" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
schemaLocation="shared-commonSimpleTypes.xsd"/>
<xsd:simpleType name="ST_VectorBaseType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="variant"/>
<xsd:enumeration value="i1"/>
<xsd:enumeration value="i2"/>
<xsd:enumeration value="i4"/>
<xsd:enumeration value="i8"/>
<xsd:enumeration value="ui1"/>
<xsd:enumeration value="ui2"/>
<xsd:enumeration value="ui4"/>
<xsd:enumeration value="ui8"/>
<xsd:enumeration value="r4"/>
<xsd:enumeration value="r8"/>
<xsd:enumeration value="lpstr"/>
<xsd:enumeration value="lpwstr"/>
<xsd:enumeration value="bstr"/>
<xsd:enumeration value="date"/>
<xsd:enumeration value="filetime"/>
<xsd:enumeration value="bool"/>
<xsd:enumeration value="cy"/>
<xsd:enumeration value="error"/>
<xsd:enumeration value="clsid"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ArrayBaseType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="variant"/>
<xsd:enumeration value="i1"/>
<xsd:enumeration value="i2"/>
<xsd:enumeration value="i4"/>
<xsd:enumeration value="int"/>
<xsd:enumeration value="ui1"/>
<xsd:enumeration value="ui2"/>
<xsd:enumeration value="ui4"/>
<xsd:enumeration value="uint"/>
<xsd:enumeration value="r4"/>
<xsd:enumeration value="r8"/>
<xsd:enumeration value="decimal"/>
<xsd:enumeration value="bstr"/>
<xsd:enumeration value="date"/>
<xsd:enumeration value="bool"/>
<xsd:enumeration value="cy"/>
<xsd:enumeration value="error"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Cy">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\s*[0-9]*\.[0-9]{4}\s*"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Error">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\s*0x[0-9A-Za-z]{8}\s*"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Empty"/>
<xsd:complexType name="CT_Null"/>
<xsd:complexType name="CT_Vector">
<xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element ref="variant"/>
<xsd:element ref="i1"/>
<xsd:element ref="i2"/>
<xsd:element ref="i4"/>
<xsd:element ref="i8"/>
<xsd:element ref="ui1"/>
<xsd:element ref="ui2"/>
<xsd:element ref="ui4"/>
<xsd:element ref="ui8"/>
<xsd:element ref="r4"/>
<xsd:element ref="r8"/>
<xsd:element ref="lpstr"/>
<xsd:element ref="lpwstr"/>
<xsd:element ref="bstr"/>
<xsd:element ref="date"/>
<xsd:element ref="filetime"/>
<xsd:element ref="bool"/>
<xsd:element ref="cy"/>
<xsd:element ref="error"/>
<xsd:element ref="clsid"/>
</xsd:choice>
<xsd:attribute name="baseType" type="ST_VectorBaseType" use="required"/>
<xsd:attribute name="size" type="xsd:unsignedInt" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Array">
<xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element ref="variant"/>
<xsd:element ref="i1"/>
<xsd:element ref="i2"/>
<xsd:element ref="i4"/>
<xsd:element ref="int"/>
<xsd:element ref="ui1"/>
<xsd:element ref="ui2"/>
<xsd:element ref="ui4"/>
<xsd:element ref="uint"/>
<xsd:element ref="r4"/>
<xsd:element ref="r8"/>
<xsd:element ref="decimal"/>
<xsd:element ref="bstr"/>
<xsd:element ref="date"/>
<xsd:element ref="bool"/>
<xsd:element ref="error"/>
<xsd:element ref="cy"/>
</xsd:choice>
<xsd:attribute name="lBounds" type="xsd:int" use="required"/>
<xsd:attribute name="uBounds" type="xsd:int" use="required"/>
<xsd:attribute name="baseType" type="ST_ArrayBaseType" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Variant">
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element ref="variant"/>
<xsd:element ref="vector"/>
<xsd:element ref="array"/>
<xsd:element ref="blob"/>
<xsd:element ref="oblob"/>
<xsd:element ref="empty"/>
<xsd:element ref="null"/>
<xsd:element ref="i1"/>
<xsd:element ref="i2"/>
<xsd:element ref="i4"/>
<xsd:element ref="i8"/>
<xsd:element ref="int"/>
<xsd:element ref="ui1"/>
<xsd:element ref="ui2"/>
<xsd:element ref="ui4"/>
<xsd:element ref="ui8"/>
<xsd:element ref="uint"/>
<xsd:element ref="r4"/>
<xsd:element ref="r8"/>
<xsd:element ref="decimal"/>
<xsd:element ref="lpstr"/>
<xsd:element ref="lpwstr"/>
<xsd:element ref="bstr"/>
<xsd:element ref="date"/>
<xsd:element ref="filetime"/>
<xsd:element ref="bool"/>
<xsd:element ref="cy"/>
<xsd:element ref="error"/>
<xsd:element ref="stream"/>
<xsd:element ref="ostream"/>
<xsd:element ref="storage"/>
<xsd:element ref="ostorage"/>
<xsd:element ref="vstream"/>
<xsd:element ref="clsid"/>
</xsd:choice>
</xsd:complexType>
<xsd:complexType name="CT_Vstream">
<xsd:simpleContent>
<xsd:extension base="xsd:base64Binary">
<xsd:attribute name="version" type="s:ST_Guid"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:element name="variant" type="CT_Variant"/>
<xsd:element name="vector" type="CT_Vector"/>
<xsd:element name="array" type="CT_Array"/>
<xsd:element name="blob" type="xsd:base64Binary"/>
<xsd:element name="oblob" type="xsd:base64Binary"/>
<xsd:element name="empty" type="CT_Empty"/>
<xsd:element name="null" type="CT_Null"/>
<xsd:element name="i1" type="xsd:byte"/>
<xsd:element name="i2" type="xsd:short"/>
<xsd:element name="i4" type="xsd:int"/>
<xsd:element name="i8" type="xsd:long"/>
<xsd:element name="int" type="xsd:int"/>
<xsd:element name="ui1" type="xsd:unsignedByte"/>
<xsd:element name="ui2" type="xsd:unsignedShort"/>
<xsd:element name="ui4" type="xsd:unsignedInt"/>
<xsd:element name="ui8" type="xsd:unsignedLong"/>
<xsd:element name="uint" type="xsd:unsignedInt"/>
<xsd:element name="r4" type="xsd:float"/>
<xsd:element name="r8" type="xsd:double"/>
<xsd:element name="decimal" type="xsd:decimal"/>
<xsd:element name="lpstr" type="xsd:string"/>
<xsd:element name="lpwstr" type="xsd:string"/>
<xsd:element name="bstr" type="xsd:string"/>
<xsd:element name="date" type="xsd:dateTime"/>
<xsd:element name="filetime" type="xsd:dateTime"/>
<xsd:element name="bool" type="xsd:boolean"/>
<xsd:element name="cy" type="ST_Cy"/>
<xsd:element name="error" type="ST_Error"/>
<xsd:element name="stream" type="xsd:base64Binary"/>
<xsd:element name="ostream" type="xsd:base64Binary"/>
<xsd:element name="storage" type="xsd:base64Binary"/>
<xsd:element name="ostorage" type="xsd:base64Binary"/>
<xsd:element name="vstream" type="CT_Vstream"/>
<xsd:element name="clsid" type="s:ST_Guid"/>
</xsd:schema>

View File

@@ -0,0 +1,582 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/math"
xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all"
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/math">
<xsd:import namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
schemaLocation="wml.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
schemaLocation="shared-commonSimpleTypes.xsd"/>
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/>
<xsd:simpleType name="ST_Integer255">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="1"/>
<xsd:maxInclusive value="255"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Integer255">
<xsd:attribute name="val" type="ST_Integer255" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_Integer2">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="-2"/>
<xsd:maxInclusive value="2"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Integer2">
<xsd:attribute name="val" type="ST_Integer2" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_SpacingRule">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="4"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_SpacingRule">
<xsd:attribute name="val" type="ST_SpacingRule" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_UnSignedInteger">
<xsd:restriction base="xsd:unsignedInt"/>
</xsd:simpleType>
<xsd:complexType name="CT_UnSignedInteger">
<xsd:attribute name="val" type="ST_UnSignedInteger" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_Char">
<xsd:restriction base="xsd:string">
<xsd:maxLength value="1"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Char">
<xsd:attribute name="val" type="ST_Char" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_OnOff">
<xsd:attribute name="val" type="s:ST_OnOff"/>
</xsd:complexType>
<xsd:complexType name="CT_String">
<xsd:attribute name="val" type="s:ST_String"/>
</xsd:complexType>
<xsd:complexType name="CT_XAlign">
<xsd:attribute name="val" type="s:ST_XAlign" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_YAlign">
<xsd:attribute name="val" type="s:ST_YAlign" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_Shp">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="centered"/>
<xsd:enumeration value="match"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Shp">
<xsd:attribute name="val" type="ST_Shp" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_FType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="bar"/>
<xsd:enumeration value="skw"/>
<xsd:enumeration value="lin"/>
<xsd:enumeration value="noBar"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_FType">
<xsd:attribute name="val" type="ST_FType" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_LimLoc">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="undOvr"/>
<xsd:enumeration value="subSup"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_LimLoc">
<xsd:attribute name="val" type="ST_LimLoc" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_TopBot">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="top"/>
<xsd:enumeration value="bot"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_TopBot">
<xsd:attribute name="val" type="ST_TopBot" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_Script">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="roman"/>
<xsd:enumeration value="script"/>
<xsd:enumeration value="fraktur"/>
<xsd:enumeration value="double-struck"/>
<xsd:enumeration value="sans-serif"/>
<xsd:enumeration value="monospace"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Script">
<xsd:attribute name="val" type="ST_Script"/>
</xsd:complexType>
<xsd:simpleType name="ST_Style">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="p"/>
<xsd:enumeration value="b"/>
<xsd:enumeration value="i"/>
<xsd:enumeration value="bi"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Style">
<xsd:attribute name="val" type="ST_Style"/>
</xsd:complexType>
<xsd:complexType name="CT_ManualBreak">
<xsd:attribute name="alnAt" type="ST_Integer255"/>
</xsd:complexType>
<xsd:group name="EG_ScriptStyle">
<xsd:sequence>
<xsd:element name="scr" minOccurs="0" type="CT_Script"/>
<xsd:element name="sty" minOccurs="0" type="CT_Style"/>
</xsd:sequence>
</xsd:group>
<xsd:complexType name="CT_RPR">
<xsd:sequence>
<xsd:element name="lit" minOccurs="0" type="CT_OnOff"/>
<xsd:choice>
<xsd:element name="nor" minOccurs="0" type="CT_OnOff"/>
<xsd:sequence>
<xsd:group ref="EG_ScriptStyle"/>
</xsd:sequence>
</xsd:choice>
<xsd:element name="brk" minOccurs="0" type="CT_ManualBreak"/>
<xsd:element name="aln" minOccurs="0" type="CT_OnOff"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Text">
<xsd:simpleContent>
<xsd:extension base="s:ST_String">
<xsd:attribute ref="xml:space" use="optional"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="CT_R">
<xsd:sequence>
<xsd:element name="rPr" type="CT_RPR" minOccurs="0"/>
<xsd:group ref="w:EG_RPr" minOccurs="0"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:group ref="w:EG_RunInnerContent"/>
<xsd:element name="t" type="CT_Text" minOccurs="0"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_CtrlPr">
<xsd:sequence>
<xsd:group ref="w:EG_RPrMath" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_AccPr">
<xsd:sequence>
<xsd:element name="chr" type="CT_Char" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Acc">
<xsd:sequence>
<xsd:element name="accPr" type="CT_AccPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_BarPr">
<xsd:sequence>
<xsd:element name="pos" type="CT_TopBot" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Bar">
<xsd:sequence>
<xsd:element name="barPr" type="CT_BarPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_BoxPr">
<xsd:sequence>
<xsd:element name="opEmu" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="noBreak" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="diff" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="brk" type="CT_ManualBreak" minOccurs="0"/>
<xsd:element name="aln" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Box">
<xsd:sequence>
<xsd:element name="boxPr" type="CT_BoxPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_BorderBoxPr">
<xsd:sequence>
<xsd:element name="hideTop" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="hideBot" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="hideLeft" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="hideRight" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="strikeH" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="strikeV" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="strikeBLTR" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="strikeTLBR" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_BorderBox">
<xsd:sequence>
<xsd:element name="borderBoxPr" type="CT_BorderBoxPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_DPr">
<xsd:sequence>
<xsd:element name="begChr" type="CT_Char" minOccurs="0"/>
<xsd:element name="sepChr" type="CT_Char" minOccurs="0"/>
<xsd:element name="endChr" type="CT_Char" minOccurs="0"/>
<xsd:element name="grow" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="shp" type="CT_Shp" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_D">
<xsd:sequence>
<xsd:element name="dPr" type="CT_DPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_EqArrPr">
<xsd:sequence>
<xsd:element name="baseJc" type="CT_YAlign" minOccurs="0"/>
<xsd:element name="maxDist" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="objDist" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="rSpRule" type="CT_SpacingRule" minOccurs="0"/>
<xsd:element name="rSp" type="CT_UnSignedInteger" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_EqArr">
<xsd:sequence>
<xsd:element name="eqArrPr" type="CT_EqArrPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_FPr">
<xsd:sequence>
<xsd:element name="type" type="CT_FType" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_F">
<xsd:sequence>
<xsd:element name="fPr" type="CT_FPr" minOccurs="0"/>
<xsd:element name="num" type="CT_OMathArg"/>
<xsd:element name="den" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_FuncPr">
<xsd:sequence>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Func">
<xsd:sequence>
<xsd:element name="funcPr" type="CT_FuncPr" minOccurs="0"/>
<xsd:element name="fName" type="CT_OMathArg"/>
<xsd:element name="e" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GroupChrPr">
<xsd:sequence>
<xsd:element name="chr" type="CT_Char" minOccurs="0"/>
<xsd:element name="pos" type="CT_TopBot" minOccurs="0"/>
<xsd:element name="vertJc" type="CT_TopBot" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GroupChr">
<xsd:sequence>
<xsd:element name="groupChrPr" type="CT_GroupChrPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_LimLowPr">
<xsd:sequence>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_LimLow">
<xsd:sequence>
<xsd:element name="limLowPr" type="CT_LimLowPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg"/>
<xsd:element name="lim" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_LimUppPr">
<xsd:sequence>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_LimUpp">
<xsd:sequence>
<xsd:element name="limUppPr" type="CT_LimUppPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg"/>
<xsd:element name="lim" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_MCPr">
<xsd:sequence>
<xsd:element name="count" type="CT_Integer255" minOccurs="0"/>
<xsd:element name="mcJc" type="CT_XAlign" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_MC">
<xsd:sequence>
<xsd:element name="mcPr" type="CT_MCPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_MCS">
<xsd:sequence>
<xsd:element name="mc" type="CT_MC" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_MPr">
<xsd:sequence>
<xsd:element name="baseJc" type="CT_YAlign" minOccurs="0"/>
<xsd:element name="plcHide" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="rSpRule" type="CT_SpacingRule" minOccurs="0"/>
<xsd:element name="cGpRule" type="CT_SpacingRule" minOccurs="0"/>
<xsd:element name="rSp" type="CT_UnSignedInteger" minOccurs="0"/>
<xsd:element name="cSp" type="CT_UnSignedInteger" minOccurs="0"/>
<xsd:element name="cGp" type="CT_UnSignedInteger" minOccurs="0"/>
<xsd:element name="mcs" type="CT_MCS" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_MR">
<xsd:sequence>
<xsd:element name="e" type="CT_OMathArg" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_M">
<xsd:sequence>
<xsd:element name="mPr" type="CT_MPr" minOccurs="0"/>
<xsd:element name="mr" type="CT_MR" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NaryPr">
<xsd:sequence>
<xsd:element name="chr" type="CT_Char" minOccurs="0"/>
<xsd:element name="limLoc" type="CT_LimLoc" minOccurs="0"/>
<xsd:element name="grow" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="subHide" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="supHide" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Nary">
<xsd:sequence>
<xsd:element name="naryPr" type="CT_NaryPr" minOccurs="0"/>
<xsd:element name="sub" type="CT_OMathArg"/>
<xsd:element name="sup" type="CT_OMathArg"/>
<xsd:element name="e" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_PhantPr">
<xsd:sequence>
<xsd:element name="show" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="zeroWid" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="zeroAsc" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="zeroDesc" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="transp" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Phant">
<xsd:sequence>
<xsd:element name="phantPr" type="CT_PhantPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_RadPr">
<xsd:sequence>
<xsd:element name="degHide" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Rad">
<xsd:sequence>
<xsd:element name="radPr" type="CT_RadPr" minOccurs="0"/>
<xsd:element name="deg" type="CT_OMathArg"/>
<xsd:element name="e" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SPrePr">
<xsd:sequence>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SPre">
<xsd:sequence>
<xsd:element name="sPrePr" type="CT_SPrePr" minOccurs="0"/>
<xsd:element name="sub" type="CT_OMathArg"/>
<xsd:element name="sup" type="CT_OMathArg"/>
<xsd:element name="e" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SSubPr">
<xsd:sequence>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SSub">
<xsd:sequence>
<xsd:element name="sSubPr" type="CT_SSubPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg"/>
<xsd:element name="sub" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SSubSupPr">
<xsd:sequence>
<xsd:element name="alnScr" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SSubSup">
<xsd:sequence>
<xsd:element name="sSubSupPr" type="CT_SSubSupPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg"/>
<xsd:element name="sub" type="CT_OMathArg"/>
<xsd:element name="sup" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SSupPr">
<xsd:sequence>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SSup">
<xsd:sequence>
<xsd:element name="sSupPr" type="CT_SSupPr" minOccurs="0"/>
<xsd:element name="e" type="CT_OMathArg"/>
<xsd:element name="sup" type="CT_OMathArg"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_OMathMathElements">
<xsd:choice>
<xsd:element name="acc" type="CT_Acc"/>
<xsd:element name="bar" type="CT_Bar"/>
<xsd:element name="box" type="CT_Box"/>
<xsd:element name="borderBox" type="CT_BorderBox"/>
<xsd:element name="d" type="CT_D"/>
<xsd:element name="eqArr" type="CT_EqArr"/>
<xsd:element name="f" type="CT_F"/>
<xsd:element name="func" type="CT_Func"/>
<xsd:element name="groupChr" type="CT_GroupChr"/>
<xsd:element name="limLow" type="CT_LimLow"/>
<xsd:element name="limUpp" type="CT_LimUpp"/>
<xsd:element name="m" type="CT_M"/>
<xsd:element name="nary" type="CT_Nary"/>
<xsd:element name="phant" type="CT_Phant"/>
<xsd:element name="rad" type="CT_Rad"/>
<xsd:element name="sPre" type="CT_SPre"/>
<xsd:element name="sSub" type="CT_SSub"/>
<xsd:element name="sSubSup" type="CT_SSubSup"/>
<xsd:element name="sSup" type="CT_SSup"/>
<xsd:element name="r" type="CT_R"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_OMathElements">
<xsd:choice>
<xsd:group ref="EG_OMathMathElements"/>
<xsd:group ref="w:EG_PContentMath"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_OMathArgPr">
<xsd:sequence>
<xsd:element name="argSz" type="CT_Integer2" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_OMathArg">
<xsd:sequence>
<xsd:element name="argPr" type="CT_OMathArgPr" minOccurs="0"/>
<xsd:group ref="EG_OMathElements" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="ctrlPr" type="CT_CtrlPr" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="ST_Jc">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="left"/>
<xsd:enumeration value="right"/>
<xsd:enumeration value="center"/>
<xsd:enumeration value="centerGroup"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_OMathJc">
<xsd:attribute name="val" type="ST_Jc"/>
</xsd:complexType>
<xsd:complexType name="CT_OMathParaPr">
<xsd:sequence>
<xsd:element name="jc" type="CT_OMathJc" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TwipsMeasure">
<xsd:attribute name="val" type="s:ST_TwipsMeasure" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_BreakBin">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="before"/>
<xsd:enumeration value="after"/>
<xsd:enumeration value="repeat"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_BreakBin">
<xsd:attribute name="val" type="ST_BreakBin"/>
</xsd:complexType>
<xsd:simpleType name="ST_BreakBinSub">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="--"/>
<xsd:enumeration value="-+"/>
<xsd:enumeration value="+-"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_BreakBinSub">
<xsd:attribute name="val" type="ST_BreakBinSub"/>
</xsd:complexType>
<xsd:complexType name="CT_MathPr">
<xsd:sequence>
<xsd:element name="mathFont" type="CT_String" minOccurs="0"/>
<xsd:element name="brkBin" type="CT_BreakBin" minOccurs="0"/>
<xsd:element name="brkBinSub" type="CT_BreakBinSub" minOccurs="0"/>
<xsd:element name="smallFrac" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="dispDef" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="lMargin" type="CT_TwipsMeasure" minOccurs="0"/>
<xsd:element name="rMargin" type="CT_TwipsMeasure" minOccurs="0"/>
<xsd:element name="defJc" type="CT_OMathJc" minOccurs="0"/>
<xsd:element name="preSp" type="CT_TwipsMeasure" minOccurs="0"/>
<xsd:element name="postSp" type="CT_TwipsMeasure" minOccurs="0"/>
<xsd:element name="interSp" type="CT_TwipsMeasure" minOccurs="0"/>
<xsd:element name="intraSp" type="CT_TwipsMeasure" minOccurs="0"/>
<xsd:choice minOccurs="0">
<xsd:element name="wrapIndent" type="CT_TwipsMeasure"/>
<xsd:element name="wrapRight" type="CT_OnOff"/>
</xsd:choice>
<xsd:element name="intLim" type="CT_LimLoc" minOccurs="0"/>
<xsd:element name="naryLim" type="CT_LimLoc" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="mathPr" type="CT_MathPr"/>
<xsd:complexType name="CT_OMathPara">
<xsd:sequence>
<xsd:element name="oMathParaPr" type="CT_OMathParaPr" minOccurs="0"/>
<xsd:element name="oMath" type="CT_OMath" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_OMath">
<xsd:sequence>
<xsd:group ref="EG_OMathElements" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="oMathPara" type="CT_OMathPara"/>
<xsd:element name="oMath" type="CT_OMath"/>
</xsd:schema>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
elementFormDefault="qualified"
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
blockDefault="#all">
<xsd:simpleType name="ST_RelationshipId">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:attribute name="id" type="ST_RelationshipId"/>
<xsd:attribute name="embed" type="ST_RelationshipId"/>
<xsd:attribute name="link" type="ST_RelationshipId"/>
<xsd:attribute name="dm" type="ST_RelationshipId" default=""/>
<xsd:attribute name="lo" type="ST_RelationshipId" default=""/>
<xsd:attribute name="qs" type="ST_RelationshipId" default=""/>
<xsd:attribute name="cs" type="ST_RelationshipId" default=""/>
<xsd:attribute name="blip" type="ST_RelationshipId" default=""/>
<xsd:attribute name="pict" type="ST_RelationshipId"/>
<xsd:attribute name="href" type="ST_RelationshipId"/>
<xsd:attribute name="topLeft" type="ST_RelationshipId"/>
<xsd:attribute name="topRight" type="ST_RelationshipId"/>
<xsd:attribute name="bottomLeft" type="ST_RelationshipId"/>
<xsd:attribute name="bottomRight" type="ST_RelationshipId"/>
</xsd:schema>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,570 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:schemas-microsoft-com:vml"
xmlns:pvml="urn:schemas-microsoft-com:office:powerpoint"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
targetNamespace="urn:schemas-microsoft-com:vml" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="urn:schemas-microsoft-com:office:office"
schemaLocation="vml-officeDrawing.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
schemaLocation="wml.xsd"/>
<xsd:import namespace="urn:schemas-microsoft-com:office:word"
schemaLocation="vml-wordprocessingDrawing.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
schemaLocation="shared-relationshipReference.xsd"/>
<xsd:import namespace="urn:schemas-microsoft-com:office:excel"
schemaLocation="vml-spreadsheetDrawing.xsd"/>
<xsd:import namespace="urn:schemas-microsoft-com:office:powerpoint"
schemaLocation="vml-presentationDrawing.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
schemaLocation="shared-commonSimpleTypes.xsd"/>
<xsd:attributeGroup name="AG_Id">
<xsd:attribute name="id" type="xsd:string" use="optional"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_Style">
<xsd:attribute name="style" type="xsd:string" use="optional"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_Type">
<xsd:attribute name="type" type="xsd:string" use="optional"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_Adj">
<xsd:attribute name="adj" type="xsd:string" use="optional"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_Path">
<xsd:attribute name="path" type="xsd:string" use="optional"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_Fill">
<xsd:attribute name="filled" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="fillcolor" type="s:ST_ColorType" use="optional"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_Chromakey">
<xsd:attribute name="chromakey" type="s:ST_ColorType" use="optional"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_Ext">
<xsd:attribute name="ext" form="qualified" type="ST_Ext"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_CoreAttributes">
<xsd:attributeGroup ref="AG_Id"/>
<xsd:attributeGroup ref="AG_Style"/>
<xsd:attribute name="href" type="xsd:string" use="optional"/>
<xsd:attribute name="target" type="xsd:string" use="optional"/>
<xsd:attribute name="class" type="xsd:string" use="optional"/>
<xsd:attribute name="title" type="xsd:string" use="optional"/>
<xsd:attribute name="alt" type="xsd:string" use="optional"/>
<xsd:attribute name="coordsize" type="xsd:string" use="optional"/>
<xsd:attribute name="coordorigin" type="xsd:string" use="optional"/>
<xsd:attribute name="wrapcoords" type="xsd:string" use="optional"/>
<xsd:attribute name="print" type="s:ST_TrueFalse" use="optional"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_ShapeAttributes">
<xsd:attributeGroup ref="AG_Chromakey"/>
<xsd:attributeGroup ref="AG_Fill"/>
<xsd:attribute name="opacity" type="xsd:string" use="optional"/>
<xsd:attribute name="stroked" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="strokecolor" type="s:ST_ColorType" use="optional"/>
<xsd:attribute name="strokeweight" type="xsd:string" use="optional"/>
<xsd:attribute name="insetpen" type="s:ST_TrueFalse" use="optional"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_OfficeCoreAttributes">
<xsd:attribute ref="o:spid"/>
<xsd:attribute ref="o:oned"/>
<xsd:attribute ref="o:regroupid"/>
<xsd:attribute ref="o:doubleclicknotify"/>
<xsd:attribute ref="o:button"/>
<xsd:attribute ref="o:userhidden"/>
<xsd:attribute ref="o:bullet"/>
<xsd:attribute ref="o:hr"/>
<xsd:attribute ref="o:hrstd"/>
<xsd:attribute ref="o:hrnoshade"/>
<xsd:attribute ref="o:hrpct"/>
<xsd:attribute ref="o:hralign"/>
<xsd:attribute ref="o:allowincell"/>
<xsd:attribute ref="o:allowoverlap"/>
<xsd:attribute ref="o:userdrawn"/>
<xsd:attribute ref="o:bordertopcolor"/>
<xsd:attribute ref="o:borderleftcolor"/>
<xsd:attribute ref="o:borderbottomcolor"/>
<xsd:attribute ref="o:borderrightcolor"/>
<xsd:attribute ref="o:dgmlayout"/>
<xsd:attribute ref="o:dgmnodekind"/>
<xsd:attribute ref="o:dgmlayoutmru"/>
<xsd:attribute ref="o:insetmode"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_OfficeShapeAttributes">
<xsd:attribute ref="o:spt"/>
<xsd:attribute ref="o:connectortype"/>
<xsd:attribute ref="o:bwmode"/>
<xsd:attribute ref="o:bwpure"/>
<xsd:attribute ref="o:bwnormal"/>
<xsd:attribute ref="o:forcedash"/>
<xsd:attribute ref="o:oleicon"/>
<xsd:attribute ref="o:ole"/>
<xsd:attribute ref="o:preferrelative"/>
<xsd:attribute ref="o:cliptowrap"/>
<xsd:attribute ref="o:clip"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_AllCoreAttributes">
<xsd:attributeGroup ref="AG_CoreAttributes"/>
<xsd:attributeGroup ref="AG_OfficeCoreAttributes"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_AllShapeAttributes">
<xsd:attributeGroup ref="AG_ShapeAttributes"/>
<xsd:attributeGroup ref="AG_OfficeShapeAttributes"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_ImageAttributes">
<xsd:attribute name="src" type="xsd:string" use="optional"/>
<xsd:attribute name="cropleft" type="xsd:string" use="optional"/>
<xsd:attribute name="croptop" type="xsd:string" use="optional"/>
<xsd:attribute name="cropright" type="xsd:string" use="optional"/>
<xsd:attribute name="cropbottom" type="xsd:string" use="optional"/>
<xsd:attribute name="gain" type="xsd:string" use="optional"/>
<xsd:attribute name="blacklevel" type="xsd:string" use="optional"/>
<xsd:attribute name="gamma" type="xsd:string" use="optional"/>
<xsd:attribute name="grayscale" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="bilevel" type="s:ST_TrueFalse" use="optional"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_StrokeAttributes">
<xsd:attribute name="on" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="weight" type="xsd:string" use="optional"/>
<xsd:attribute name="color" type="s:ST_ColorType" use="optional"/>
<xsd:attribute name="opacity" type="xsd:string" use="optional"/>
<xsd:attribute name="linestyle" type="ST_StrokeLineStyle" use="optional"/>
<xsd:attribute name="miterlimit" type="xsd:decimal" use="optional"/>
<xsd:attribute name="joinstyle" type="ST_StrokeJoinStyle" use="optional"/>
<xsd:attribute name="endcap" type="ST_StrokeEndCap" use="optional"/>
<xsd:attribute name="dashstyle" type="xsd:string" use="optional"/>
<xsd:attribute name="filltype" type="ST_FillType" use="optional"/>
<xsd:attribute name="src" type="xsd:string" use="optional"/>
<xsd:attribute name="imageaspect" type="ST_ImageAspect" use="optional"/>
<xsd:attribute name="imagesize" type="xsd:string" use="optional"/>
<xsd:attribute name="imagealignshape" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="color2" type="s:ST_ColorType" use="optional"/>
<xsd:attribute name="startarrow" type="ST_StrokeArrowType" use="optional"/>
<xsd:attribute name="startarrowwidth" type="ST_StrokeArrowWidth" use="optional"/>
<xsd:attribute name="startarrowlength" type="ST_StrokeArrowLength" use="optional"/>
<xsd:attribute name="endarrow" type="ST_StrokeArrowType" use="optional"/>
<xsd:attribute name="endarrowwidth" type="ST_StrokeArrowWidth" use="optional"/>
<xsd:attribute name="endarrowlength" type="ST_StrokeArrowLength" use="optional"/>
<xsd:attribute ref="o:href"/>
<xsd:attribute ref="o:althref"/>
<xsd:attribute ref="o:title"/>
<xsd:attribute ref="o:forcedash"/>
<xsd:attribute ref="r:id" use="optional"/>
<xsd:attribute name="insetpen" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute ref="o:relid"/>
</xsd:attributeGroup>
<xsd:group name="EG_ShapeElements">
<xsd:choice>
<xsd:element ref="path"/>
<xsd:element ref="formulas"/>
<xsd:element ref="handles"/>
<xsd:element ref="fill"/>
<xsd:element ref="stroke"/>
<xsd:element ref="shadow"/>
<xsd:element ref="textbox"/>
<xsd:element ref="textpath"/>
<xsd:element ref="imagedata"/>
<xsd:element ref="o:skew"/>
<xsd:element ref="o:extrusion"/>
<xsd:element ref="o:callout"/>
<xsd:element ref="o:lock"/>
<xsd:element ref="o:clippath"/>
<xsd:element ref="o:signatureline"/>
<xsd:element ref="w10:wrap"/>
<xsd:element ref="w10:anchorlock"/>
<xsd:element ref="w10:bordertop"/>
<xsd:element ref="w10:borderbottom"/>
<xsd:element ref="w10:borderleft"/>
<xsd:element ref="w10:borderright"/>
<xsd:element ref="x:ClientData" minOccurs="0"/>
<xsd:element ref="pvml:textdata" minOccurs="0"/>
</xsd:choice>
</xsd:group>
<xsd:element name="shape" type="CT_Shape"/>
<xsd:element name="shapetype" type="CT_Shapetype"/>
<xsd:element name="group" type="CT_Group"/>
<xsd:element name="background" type="CT_Background"/>
<xsd:complexType name="CT_Shape">
<xsd:choice maxOccurs="unbounded">
<xsd:group ref="EG_ShapeElements"/>
<xsd:element ref="o:ink"/>
<xsd:element ref="pvml:iscomment"/>
<xsd:element ref="o:equationxml"/>
</xsd:choice>
<xsd:attributeGroup ref="AG_AllCoreAttributes"/>
<xsd:attributeGroup ref="AG_AllShapeAttributes"/>
<xsd:attributeGroup ref="AG_Type"/>
<xsd:attributeGroup ref="AG_Adj"/>
<xsd:attributeGroup ref="AG_Path"/>
<xsd:attribute ref="o:gfxdata"/>
<xsd:attribute name="equationxml" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Shapetype">
<xsd:sequence>
<xsd:group ref="EG_ShapeElements" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="o:complex" minOccurs="0"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_AllCoreAttributes"/>
<xsd:attributeGroup ref="AG_AllShapeAttributes"/>
<xsd:attributeGroup ref="AG_Adj"/>
<xsd:attributeGroup ref="AG_Path"/>
<xsd:attribute ref="o:master"/>
</xsd:complexType>
<xsd:complexType name="CT_Group">
<xsd:choice maxOccurs="unbounded">
<xsd:group ref="EG_ShapeElements"/>
<xsd:element ref="group"/>
<xsd:element ref="shape"/>
<xsd:element ref="shapetype"/>
<xsd:element ref="arc"/>
<xsd:element ref="curve"/>
<xsd:element ref="image"/>
<xsd:element ref="line"/>
<xsd:element ref="oval"/>
<xsd:element ref="polyline"/>
<xsd:element ref="rect"/>
<xsd:element ref="roundrect"/>
<xsd:element ref="o:diagram"/>
</xsd:choice>
<xsd:attributeGroup ref="AG_AllCoreAttributes"/>
<xsd:attributeGroup ref="AG_Fill"/>
<xsd:attribute name="editas" type="ST_EditAs" use="optional"/>
<xsd:attribute ref="o:tableproperties"/>
<xsd:attribute ref="o:tablelimits"/>
</xsd:complexType>
<xsd:complexType name="CT_Background">
<xsd:sequence>
<xsd:element ref="fill" minOccurs="0"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_Id"/>
<xsd:attributeGroup ref="AG_Fill"/>
<xsd:attribute ref="o:bwmode"/>
<xsd:attribute ref="o:bwpure"/>
<xsd:attribute ref="o:bwnormal"/>
<xsd:attribute ref="o:targetscreensize"/>
</xsd:complexType>
<xsd:element name="fill" type="CT_Fill"/>
<xsd:element name="formulas" type="CT_Formulas"/>
<xsd:element name="handles" type="CT_Handles"/>
<xsd:element name="imagedata" type="CT_ImageData"/>
<xsd:element name="path" type="CT_Path"/>
<xsd:element name="textbox" type="CT_Textbox"/>
<xsd:element name="shadow" type="CT_Shadow"/>
<xsd:element name="stroke" type="CT_Stroke"/>
<xsd:element name="textpath" type="CT_TextPath"/>
<xsd:complexType name="CT_Fill">
<xsd:sequence>
<xsd:element ref="o:fill" minOccurs="0"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_Id"/>
<xsd:attribute name="type" type="ST_FillType" use="optional"/>
<xsd:attribute name="on" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="color" type="s:ST_ColorType" use="optional"/>
<xsd:attribute name="opacity" type="xsd:string" use="optional"/>
<xsd:attribute name="color2" type="s:ST_ColorType" use="optional"/>
<xsd:attribute name="src" type="xsd:string" use="optional"/>
<xsd:attribute ref="o:href"/>
<xsd:attribute ref="o:althref"/>
<xsd:attribute name="size" type="xsd:string" use="optional"/>
<xsd:attribute name="origin" type="xsd:string" use="optional"/>
<xsd:attribute name="position" type="xsd:string" use="optional"/>
<xsd:attribute name="aspect" type="ST_ImageAspect" use="optional"/>
<xsd:attribute name="colors" type="xsd:string" use="optional"/>
<xsd:attribute name="angle" type="xsd:decimal" use="optional"/>
<xsd:attribute name="alignshape" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="focus" type="xsd:string" use="optional"/>
<xsd:attribute name="focussize" type="xsd:string" use="optional"/>
<xsd:attribute name="focusposition" type="xsd:string" use="optional"/>
<xsd:attribute name="method" type="ST_FillMethod" use="optional"/>
<xsd:attribute ref="o:detectmouseclick"/>
<xsd:attribute ref="o:title"/>
<xsd:attribute ref="o:opacity2"/>
<xsd:attribute name="recolor" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="rotate" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute ref="r:id" use="optional"/>
<xsd:attribute ref="o:relid" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Formulas">
<xsd:sequence>
<xsd:element name="f" type="CT_F" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_F">
<xsd:attribute name="eqn" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="CT_Handles">
<xsd:sequence>
<xsd:element name="h" type="CT_H" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_H">
<xsd:attribute name="position" type="xsd:string"/>
<xsd:attribute name="polar" type="xsd:string"/>
<xsd:attribute name="map" type="xsd:string"/>
<xsd:attribute name="invx" type="s:ST_TrueFalse"/>
<xsd:attribute name="invy" type="s:ST_TrueFalse"/>
<xsd:attribute name="switch" type="s:ST_TrueFalseBlank"/>
<xsd:attribute name="xrange" type="xsd:string"/>
<xsd:attribute name="yrange" type="xsd:string"/>
<xsd:attribute name="radiusrange" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="CT_ImageData">
<xsd:attributeGroup ref="AG_Id"/>
<xsd:attributeGroup ref="AG_ImageAttributes"/>
<xsd:attributeGroup ref="AG_Chromakey"/>
<xsd:attribute name="embosscolor" type="s:ST_ColorType" use="optional"/>
<xsd:attribute name="recolortarget" type="s:ST_ColorType"/>
<xsd:attribute ref="o:href"/>
<xsd:attribute ref="o:althref"/>
<xsd:attribute ref="o:title"/>
<xsd:attribute ref="o:oleid"/>
<xsd:attribute ref="o:detectmouseclick"/>
<xsd:attribute ref="o:movie"/>
<xsd:attribute ref="o:relid"/>
<xsd:attribute ref="r:id"/>
<xsd:attribute ref="r:pict"/>
<xsd:attribute ref="r:href"/>
</xsd:complexType>
<xsd:complexType name="CT_Path">
<xsd:attributeGroup ref="AG_Id"/>
<xsd:attribute name="v" type="xsd:string" use="optional"/>
<xsd:attribute name="limo" type="xsd:string" use="optional"/>
<xsd:attribute name="textboxrect" type="xsd:string" use="optional"/>
<xsd:attribute name="fillok" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="strokeok" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="shadowok" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="arrowok" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="gradientshapeok" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="textpathok" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="insetpenok" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute ref="o:connecttype"/>
<xsd:attribute ref="o:connectlocs"/>
<xsd:attribute ref="o:connectangles"/>
<xsd:attribute ref="o:extrusionok"/>
</xsd:complexType>
<xsd:complexType name="CT_Shadow">
<xsd:attributeGroup ref="AG_Id"/>
<xsd:attribute name="on" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="type" type="ST_ShadowType" use="optional"/>
<xsd:attribute name="obscured" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="color" type="s:ST_ColorType" use="optional"/>
<xsd:attribute name="opacity" type="xsd:string" use="optional"/>
<xsd:attribute name="offset" type="xsd:string" use="optional"/>
<xsd:attribute name="color2" type="s:ST_ColorType" use="optional"/>
<xsd:attribute name="offset2" type="xsd:string" use="optional"/>
<xsd:attribute name="origin" type="xsd:string" use="optional"/>
<xsd:attribute name="matrix" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Stroke">
<xsd:sequence>
<xsd:element ref="o:left" minOccurs="0"/>
<xsd:element ref="o:top" minOccurs="0"/>
<xsd:element ref="o:right" minOccurs="0"/>
<xsd:element ref="o:bottom" minOccurs="0"/>
<xsd:element ref="o:column" minOccurs="0"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_Id"/>
<xsd:attributeGroup ref="AG_StrokeAttributes"/>
</xsd:complexType>
<xsd:complexType name="CT_Textbox">
<xsd:choice>
<xsd:element ref="w:txbxContent" minOccurs="0"/>
<xsd:any namespace="##local" processContents="skip"/>
</xsd:choice>
<xsd:attributeGroup ref="AG_Id"/>
<xsd:attributeGroup ref="AG_Style"/>
<xsd:attribute name="inset" type="xsd:string" use="optional"/>
<xsd:attribute ref="o:singleclick"/>
<xsd:attribute ref="o:insetmode"/>
</xsd:complexType>
<xsd:complexType name="CT_TextPath">
<xsd:attributeGroup ref="AG_Id"/>
<xsd:attributeGroup ref="AG_Style"/>
<xsd:attribute name="on" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="fitshape" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="fitpath" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="trim" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="xscale" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="string" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:element name="arc" type="CT_Arc"/>
<xsd:element name="curve" type="CT_Curve"/>
<xsd:element name="image" type="CT_Image"/>
<xsd:element name="line" type="CT_Line"/>
<xsd:element name="oval" type="CT_Oval"/>
<xsd:element name="polyline" type="CT_PolyLine"/>
<xsd:element name="rect" type="CT_Rect"/>
<xsd:element name="roundrect" type="CT_RoundRect"/>
<xsd:complexType name="CT_Arc">
<xsd:sequence>
<xsd:group ref="EG_ShapeElements" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_AllCoreAttributes"/>
<xsd:attributeGroup ref="AG_AllShapeAttributes"/>
<xsd:attribute name="startAngle" type="xsd:decimal" use="optional"/>
<xsd:attribute name="endAngle" type="xsd:decimal" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Curve">
<xsd:sequence>
<xsd:group ref="EG_ShapeElements" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_AllCoreAttributes"/>
<xsd:attributeGroup ref="AG_AllShapeAttributes"/>
<xsd:attribute name="from" type="xsd:string" use="optional"/>
<xsd:attribute name="control1" type="xsd:string" use="optional"/>
<xsd:attribute name="control2" type="xsd:string" use="optional"/>
<xsd:attribute name="to" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Image">
<xsd:sequence>
<xsd:group ref="EG_ShapeElements" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_AllCoreAttributes"/>
<xsd:attributeGroup ref="AG_AllShapeAttributes"/>
<xsd:attributeGroup ref="AG_ImageAttributes"/>
</xsd:complexType>
<xsd:complexType name="CT_Line">
<xsd:sequence>
<xsd:group ref="EG_ShapeElements" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_AllCoreAttributes"/>
<xsd:attributeGroup ref="AG_AllShapeAttributes"/>
<xsd:attribute name="from" type="xsd:string" use="optional"/>
<xsd:attribute name="to" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Oval">
<xsd:choice maxOccurs="unbounded">
<xsd:group ref="EG_ShapeElements" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
<xsd:attributeGroup ref="AG_AllCoreAttributes"/>
<xsd:attributeGroup ref="AG_AllShapeAttributes"/>
</xsd:complexType>
<xsd:complexType name="CT_PolyLine">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:group ref="EG_ShapeElements"/>
<xsd:element ref="o:ink"/>
</xsd:choice>
<xsd:attributeGroup ref="AG_AllCoreAttributes"/>
<xsd:attributeGroup ref="AG_AllShapeAttributes"/>
<xsd:attribute name="points" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Rect">
<xsd:choice maxOccurs="unbounded">
<xsd:group ref="EG_ShapeElements" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
<xsd:attributeGroup ref="AG_AllCoreAttributes"/>
<xsd:attributeGroup ref="AG_AllShapeAttributes"/>
</xsd:complexType>
<xsd:complexType name="CT_RoundRect">
<xsd:choice maxOccurs="unbounded">
<xsd:group ref="EG_ShapeElements" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
<xsd:attributeGroup ref="AG_AllCoreAttributes"/>
<xsd:attributeGroup ref="AG_AllShapeAttributes"/>
<xsd:attribute name="arcsize" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:simpleType name="ST_Ext">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="view"/>
<xsd:enumeration value="edit"/>
<xsd:enumeration value="backwardCompatible"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_FillType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="solid"/>
<xsd:enumeration value="gradient"/>
<xsd:enumeration value="gradientRadial"/>
<xsd:enumeration value="tile"/>
<xsd:enumeration value="pattern"/>
<xsd:enumeration value="frame"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_FillMethod">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="none"/>
<xsd:enumeration value="linear"/>
<xsd:enumeration value="sigma"/>
<xsd:enumeration value="any"/>
<xsd:enumeration value="linear sigma"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ShadowType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="single"/>
<xsd:enumeration value="double"/>
<xsd:enumeration value="emboss"/>
<xsd:enumeration value="perspective"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_StrokeLineStyle">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="single"/>
<xsd:enumeration value="thinThin"/>
<xsd:enumeration value="thinThick"/>
<xsd:enumeration value="thickThin"/>
<xsd:enumeration value="thickBetweenThin"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_StrokeJoinStyle">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="round"/>
<xsd:enumeration value="bevel"/>
<xsd:enumeration value="miter"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_StrokeEndCap">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="flat"/>
<xsd:enumeration value="square"/>
<xsd:enumeration value="round"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_StrokeArrowLength">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="short"/>
<xsd:enumeration value="medium"/>
<xsd:enumeration value="long"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_StrokeArrowWidth">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="narrow"/>
<xsd:enumeration value="medium"/>
<xsd:enumeration value="wide"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_StrokeArrowType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="none"/>
<xsd:enumeration value="block"/>
<xsd:enumeration value="classic"/>
<xsd:enumeration value="oval"/>
<xsd:enumeration value="diamond"/>
<xsd:enumeration value="open"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ImageAspect">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="ignore"/>
<xsd:enumeration value="atMost"/>
<xsd:enumeration value="atLeast"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_EditAs">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="canvas"/>
<xsd:enumeration value="orgchart"/>
<xsd:enumeration value="radial"/>
<xsd:enumeration value="cycle"/>
<xsd:enumeration value="stacked"/>
<xsd:enumeration value="venn"/>
<xsd:enumeration value="bullseye"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@@ -0,0 +1,509 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
targetNamespace="urn:schemas-microsoft-com:office:office" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="urn:schemas-microsoft-com:vml" schemaLocation="vml-main.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
schemaLocation="shared-relationshipReference.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
schemaLocation="shared-commonSimpleTypes.xsd"/>
<xsd:attribute name="bwmode" type="ST_BWMode"/>
<xsd:attribute name="bwpure" type="ST_BWMode"/>
<xsd:attribute name="bwnormal" type="ST_BWMode"/>
<xsd:attribute name="targetscreensize" type="ST_ScreenSize"/>
<xsd:attribute name="insetmode" type="ST_InsetMode" default="custom"/>
<xsd:attribute name="spt" type="xsd:float"/>
<xsd:attribute name="wrapcoords" type="xsd:string"/>
<xsd:attribute name="oned" type="s:ST_TrueFalse"/>
<xsd:attribute name="regroupid" type="xsd:integer"/>
<xsd:attribute name="doubleclicknotify" type="s:ST_TrueFalse"/>
<xsd:attribute name="connectortype" type="ST_ConnectorType" default="straight"/>
<xsd:attribute name="button" type="s:ST_TrueFalse"/>
<xsd:attribute name="userhidden" type="s:ST_TrueFalse"/>
<xsd:attribute name="forcedash" type="s:ST_TrueFalse"/>
<xsd:attribute name="oleicon" type="s:ST_TrueFalse"/>
<xsd:attribute name="ole" type="s:ST_TrueFalseBlank"/>
<xsd:attribute name="preferrelative" type="s:ST_TrueFalse"/>
<xsd:attribute name="cliptowrap" type="s:ST_TrueFalse"/>
<xsd:attribute name="clip" type="s:ST_TrueFalse"/>
<xsd:attribute name="bullet" type="s:ST_TrueFalse"/>
<xsd:attribute name="hr" type="s:ST_TrueFalse"/>
<xsd:attribute name="hrstd" type="s:ST_TrueFalse"/>
<xsd:attribute name="hrnoshade" type="s:ST_TrueFalse"/>
<xsd:attribute name="hrpct" type="xsd:float"/>
<xsd:attribute name="hralign" type="ST_HrAlign" default="left"/>
<xsd:attribute name="allowincell" type="s:ST_TrueFalse"/>
<xsd:attribute name="allowoverlap" type="s:ST_TrueFalse"/>
<xsd:attribute name="userdrawn" type="s:ST_TrueFalse"/>
<xsd:attribute name="bordertopcolor" type="xsd:string"/>
<xsd:attribute name="borderleftcolor" type="xsd:string"/>
<xsd:attribute name="borderbottomcolor" type="xsd:string"/>
<xsd:attribute name="borderrightcolor" type="xsd:string"/>
<xsd:attribute name="connecttype" type="ST_ConnectType"/>
<xsd:attribute name="connectlocs" type="xsd:string"/>
<xsd:attribute name="connectangles" type="xsd:string"/>
<xsd:attribute name="master" type="xsd:string"/>
<xsd:attribute name="extrusionok" type="s:ST_TrueFalse"/>
<xsd:attribute name="href" type="xsd:string"/>
<xsd:attribute name="althref" type="xsd:string"/>
<xsd:attribute name="title" type="xsd:string"/>
<xsd:attribute name="singleclick" type="s:ST_TrueFalse"/>
<xsd:attribute name="oleid" type="xsd:float"/>
<xsd:attribute name="detectmouseclick" type="s:ST_TrueFalse"/>
<xsd:attribute name="movie" type="xsd:float"/>
<xsd:attribute name="spid" type="xsd:string"/>
<xsd:attribute name="opacity2" type="xsd:string"/>
<xsd:attribute name="relid" type="r:ST_RelationshipId"/>
<xsd:attribute name="dgmlayout" type="ST_DiagramLayout"/>
<xsd:attribute name="dgmnodekind" type="xsd:integer"/>
<xsd:attribute name="dgmlayoutmru" type="ST_DiagramLayout"/>
<xsd:attribute name="gfxdata" type="xsd:base64Binary"/>
<xsd:attribute name="tableproperties" type="xsd:string"/>
<xsd:attribute name="tablelimits" type="xsd:string"/>
<xsd:element name="shapedefaults" type="CT_ShapeDefaults"/>
<xsd:element name="shapelayout" type="CT_ShapeLayout"/>
<xsd:element name="signatureline" type="CT_SignatureLine"/>
<xsd:element name="ink" type="CT_Ink"/>
<xsd:element name="diagram" type="CT_Diagram"/>
<xsd:element name="equationxml" type="CT_EquationXml"/>
<xsd:complexType name="CT_ShapeDefaults">
<xsd:all minOccurs="0">
<xsd:element ref="v:fill" minOccurs="0"/>
<xsd:element ref="v:stroke" minOccurs="0"/>
<xsd:element ref="v:textbox" minOccurs="0"/>
<xsd:element ref="v:shadow" minOccurs="0"/>
<xsd:element ref="skew" minOccurs="0"/>
<xsd:element ref="extrusion" minOccurs="0"/>
<xsd:element ref="callout" minOccurs="0"/>
<xsd:element ref="lock" minOccurs="0"/>
<xsd:element name="colormru" minOccurs="0" type="CT_ColorMru"/>
<xsd:element name="colormenu" minOccurs="0" type="CT_ColorMenu"/>
</xsd:all>
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="spidmax" type="xsd:integer" use="optional"/>
<xsd:attribute name="style" type="xsd:string" use="optional"/>
<xsd:attribute name="fill" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="fillcolor" type="s:ST_ColorType" use="optional"/>
<xsd:attribute name="stroke" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="strokecolor" type="s:ST_ColorType"/>
<xsd:attribute name="allowincell" form="qualified" type="s:ST_TrueFalse"/>
</xsd:complexType>
<xsd:complexType name="CT_Ink">
<xsd:sequence/>
<xsd:attribute name="i" type="xsd:string"/>
<xsd:attribute name="annotation" type="s:ST_TrueFalse"/>
<xsd:attribute name="contentType" type="ST_ContentType" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_SignatureLine">
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="issignatureline" type="s:ST_TrueFalse"/>
<xsd:attribute name="id" type="s:ST_Guid"/>
<xsd:attribute name="provid" type="s:ST_Guid"/>
<xsd:attribute name="signinginstructionsset" type="s:ST_TrueFalse"/>
<xsd:attribute name="allowcomments" type="s:ST_TrueFalse"/>
<xsd:attribute name="showsigndate" type="s:ST_TrueFalse"/>
<xsd:attribute name="suggestedsigner" type="xsd:string" form="qualified"/>
<xsd:attribute name="suggestedsigner2" type="xsd:string" form="qualified"/>
<xsd:attribute name="suggestedsigneremail" type="xsd:string" form="qualified"/>
<xsd:attribute name="signinginstructions" type="xsd:string"/>
<xsd:attribute name="addlxml" type="xsd:string"/>
<xsd:attribute name="sigprovurl" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="CT_ShapeLayout">
<xsd:all>
<xsd:element name="idmap" type="CT_IdMap" minOccurs="0"/>
<xsd:element name="regrouptable" type="CT_RegroupTable" minOccurs="0"/>
<xsd:element name="rules" type="CT_Rules" minOccurs="0"/>
</xsd:all>
<xsd:attributeGroup ref="v:AG_Ext"/>
</xsd:complexType>
<xsd:complexType name="CT_IdMap">
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="data" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_RegroupTable">
<xsd:sequence>
<xsd:element name="entry" type="CT_Entry" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attributeGroup ref="v:AG_Ext"/>
</xsd:complexType>
<xsd:complexType name="CT_Entry">
<xsd:attribute name="new" type="xsd:int" use="optional"/>
<xsd:attribute name="old" type="xsd:int" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Rules">
<xsd:sequence>
<xsd:element name="r" type="CT_R" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attributeGroup ref="v:AG_Ext"/>
</xsd:complexType>
<xsd:complexType name="CT_R">
<xsd:sequence>
<xsd:element name="proxy" type="CT_Proxy" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string" use="required"/>
<xsd:attribute name="type" type="ST_RType" use="optional"/>
<xsd:attribute name="how" type="ST_How" use="optional"/>
<xsd:attribute name="idref" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Proxy">
<xsd:attribute name="start" type="s:ST_TrueFalseBlank" use="optional" default="false"/>
<xsd:attribute name="end" type="s:ST_TrueFalseBlank" use="optional" default="false"/>
<xsd:attribute name="idref" type="xsd:string" use="optional"/>
<xsd:attribute name="connectloc" type="xsd:int" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Diagram">
<xsd:sequence>
<xsd:element name="relationtable" type="CT_RelationTable" minOccurs="0"/>
</xsd:sequence>
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="dgmstyle" type="xsd:integer" use="optional"/>
<xsd:attribute name="autoformat" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="reverse" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="autolayout" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="dgmscalex" type="xsd:integer" use="optional"/>
<xsd:attribute name="dgmscaley" type="xsd:integer" use="optional"/>
<xsd:attribute name="dgmfontsize" type="xsd:integer" use="optional"/>
<xsd:attribute name="constrainbounds" type="xsd:string" use="optional"/>
<xsd:attribute name="dgmbasetextscale" type="xsd:integer" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_EquationXml">
<xsd:sequence>
<xsd:any namespace="##any"/>
</xsd:sequence>
<xsd:attribute name="contentType" type="ST_AlternateMathContentType" use="optional"/>
</xsd:complexType>
<xsd:simpleType name="ST_AlternateMathContentType">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:complexType name="CT_RelationTable">
<xsd:sequence>
<xsd:element name="rel" type="CT_Relation" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attributeGroup ref="v:AG_Ext"/>
</xsd:complexType>
<xsd:complexType name="CT_Relation">
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="idsrc" type="xsd:string" use="optional"/>
<xsd:attribute name="iddest" type="xsd:string" use="optional"/>
<xsd:attribute name="idcntr" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_ColorMru">
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="colors" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="CT_ColorMenu">
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="strokecolor" type="s:ST_ColorType"/>
<xsd:attribute name="fillcolor" type="s:ST_ColorType"/>
<xsd:attribute name="shadowcolor" type="s:ST_ColorType"/>
<xsd:attribute name="extrusioncolor" type="s:ST_ColorType"/>
</xsd:complexType>
<xsd:element name="skew" type="CT_Skew"/>
<xsd:element name="extrusion" type="CT_Extrusion"/>
<xsd:element name="callout" type="CT_Callout"/>
<xsd:element name="lock" type="CT_Lock"/>
<xsd:element name="OLEObject" type="CT_OLEObject"/>
<xsd:element name="complex" type="CT_Complex"/>
<xsd:element name="left" type="CT_StrokeChild"/>
<xsd:element name="top" type="CT_StrokeChild"/>
<xsd:element name="right" type="CT_StrokeChild"/>
<xsd:element name="bottom" type="CT_StrokeChild"/>
<xsd:element name="column" type="CT_StrokeChild"/>
<xsd:element name="clippath" type="CT_ClipPath"/>
<xsd:element name="fill" type="CT_Fill"/>
<xsd:complexType name="CT_Skew">
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="id" type="xsd:string" use="optional"/>
<xsd:attribute name="on" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="offset" type="xsd:string" use="optional"/>
<xsd:attribute name="origin" type="xsd:string" use="optional"/>
<xsd:attribute name="matrix" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Extrusion">
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="on" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="type" type="ST_ExtrusionType" default="parallel" use="optional"/>
<xsd:attribute name="render" type="ST_ExtrusionRender" default="solid" use="optional"/>
<xsd:attribute name="viewpointorigin" type="xsd:string" use="optional"/>
<xsd:attribute name="viewpoint" type="xsd:string" use="optional"/>
<xsd:attribute name="plane" type="ST_ExtrusionPlane" default="XY" use="optional"/>
<xsd:attribute name="skewangle" type="xsd:float" use="optional"/>
<xsd:attribute name="skewamt" type="xsd:string" use="optional"/>
<xsd:attribute name="foredepth" type="xsd:string" use="optional"/>
<xsd:attribute name="backdepth" type="xsd:string" use="optional"/>
<xsd:attribute name="orientation" type="xsd:string" use="optional"/>
<xsd:attribute name="orientationangle" type="xsd:float" use="optional"/>
<xsd:attribute name="lockrotationcenter" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="autorotationcenter" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="rotationcenter" type="xsd:string" use="optional"/>
<xsd:attribute name="rotationangle" type="xsd:string" use="optional"/>
<xsd:attribute name="colormode" type="ST_ColorMode" use="optional"/>
<xsd:attribute name="color" type="s:ST_ColorType" use="optional"/>
<xsd:attribute name="shininess" type="xsd:float" use="optional"/>
<xsd:attribute name="specularity" type="xsd:string" use="optional"/>
<xsd:attribute name="diffusity" type="xsd:string" use="optional"/>
<xsd:attribute name="metal" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="edge" type="xsd:string" use="optional"/>
<xsd:attribute name="facet" type="xsd:string" use="optional"/>
<xsd:attribute name="lightface" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="brightness" type="xsd:string" use="optional"/>
<xsd:attribute name="lightposition" type="xsd:string" use="optional"/>
<xsd:attribute name="lightlevel" type="xsd:string" use="optional"/>
<xsd:attribute name="lightharsh" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="lightposition2" type="xsd:string" use="optional"/>
<xsd:attribute name="lightlevel2" type="xsd:string" use="optional"/>
<xsd:attribute name="lightharsh2" type="s:ST_TrueFalse" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Callout">
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="on" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="type" type="xsd:string" use="optional"/>
<xsd:attribute name="gap" type="xsd:string" use="optional"/>
<xsd:attribute name="angle" type="ST_Angle" use="optional"/>
<xsd:attribute name="dropauto" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="drop" type="ST_CalloutDrop" use="optional"/>
<xsd:attribute name="distance" type="xsd:string" use="optional"/>
<xsd:attribute name="lengthspecified" type="s:ST_TrueFalse" default="f" use="optional"/>
<xsd:attribute name="length" type="xsd:string" use="optional"/>
<xsd:attribute name="accentbar" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="textborder" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="minusx" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="minusy" type="s:ST_TrueFalse" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Lock">
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="position" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="selection" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="grouping" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="ungrouping" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="rotation" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="cropping" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="verticies" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="adjusthandles" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="text" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="aspectratio" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="shapetype" type="s:ST_TrueFalse" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_OLEObject">
<xsd:sequence>
<xsd:element name="LinkType" type="ST_OLELinkType" minOccurs="0"/>
<xsd:element name="LockedField" type="s:ST_TrueFalseBlank" minOccurs="0"/>
<xsd:element name="FieldCodes" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="Type" type="ST_OLEType" use="optional"/>
<xsd:attribute name="ProgID" type="xsd:string" use="optional"/>
<xsd:attribute name="ShapeID" type="xsd:string" use="optional"/>
<xsd:attribute name="DrawAspect" type="ST_OLEDrawAspect" use="optional"/>
<xsd:attribute name="ObjectID" type="xsd:string" use="optional"/>
<xsd:attribute ref="r:id" use="optional"/>
<xsd:attribute name="UpdateMode" type="ST_OLEUpdateMode" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Complex">
<xsd:attributeGroup ref="v:AG_Ext"/>
</xsd:complexType>
<xsd:complexType name="CT_StrokeChild">
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="on" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="weight" type="xsd:string" use="optional"/>
<xsd:attribute name="color" type="s:ST_ColorType" use="optional"/>
<xsd:attribute name="color2" type="s:ST_ColorType" use="optional"/>
<xsd:attribute name="opacity" type="xsd:string" use="optional"/>
<xsd:attribute name="linestyle" type="v:ST_StrokeLineStyle" use="optional"/>
<xsd:attribute name="miterlimit" type="xsd:decimal" use="optional"/>
<xsd:attribute name="joinstyle" type="v:ST_StrokeJoinStyle" use="optional"/>
<xsd:attribute name="endcap" type="v:ST_StrokeEndCap" use="optional"/>
<xsd:attribute name="dashstyle" type="xsd:string" use="optional"/>
<xsd:attribute name="insetpen" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="filltype" type="v:ST_FillType" use="optional"/>
<xsd:attribute name="src" type="xsd:string" use="optional"/>
<xsd:attribute name="imageaspect" type="v:ST_ImageAspect" use="optional"/>
<xsd:attribute name="imagesize" type="xsd:string" use="optional"/>
<xsd:attribute name="imagealignshape" type="s:ST_TrueFalse" use="optional"/>
<xsd:attribute name="startarrow" type="v:ST_StrokeArrowType" use="optional"/>
<xsd:attribute name="startarrowwidth" type="v:ST_StrokeArrowWidth" use="optional"/>
<xsd:attribute name="startarrowlength" type="v:ST_StrokeArrowLength" use="optional"/>
<xsd:attribute name="endarrow" type="v:ST_StrokeArrowType" use="optional"/>
<xsd:attribute name="endarrowwidth" type="v:ST_StrokeArrowWidth" use="optional"/>
<xsd:attribute name="endarrowlength" type="v:ST_StrokeArrowLength" use="optional"/>
<xsd:attribute ref="href"/>
<xsd:attribute ref="althref"/>
<xsd:attribute ref="title"/>
<xsd:attribute ref="forcedash"/>
</xsd:complexType>
<xsd:complexType name="CT_ClipPath">
<xsd:attribute name="v" type="xsd:string" use="required" form="qualified"/>
</xsd:complexType>
<xsd:complexType name="CT_Fill">
<xsd:attributeGroup ref="v:AG_Ext"/>
<xsd:attribute name="type" type="ST_FillType"/>
</xsd:complexType>
<xsd:simpleType name="ST_RType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="arc"/>
<xsd:enumeration value="callout"/>
<xsd:enumeration value="connector"/>
<xsd:enumeration value="align"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_How">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="top"/>
<xsd:enumeration value="middle"/>
<xsd:enumeration value="bottom"/>
<xsd:enumeration value="left"/>
<xsd:enumeration value="center"/>
<xsd:enumeration value="right"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_BWMode">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="color"/>
<xsd:enumeration value="auto"/>
<xsd:enumeration value="grayScale"/>
<xsd:enumeration value="lightGrayscale"/>
<xsd:enumeration value="inverseGray"/>
<xsd:enumeration value="grayOutline"/>
<xsd:enumeration value="highContrast"/>
<xsd:enumeration value="black"/>
<xsd:enumeration value="white"/>
<xsd:enumeration value="hide"/>
<xsd:enumeration value="undrawn"/>
<xsd:enumeration value="blackTextAndLines"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ScreenSize">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="544,376"/>
<xsd:enumeration value="640,480"/>
<xsd:enumeration value="720,512"/>
<xsd:enumeration value="800,600"/>
<xsd:enumeration value="1024,768"/>
<xsd:enumeration value="1152,862"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_InsetMode">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="auto"/>
<xsd:enumeration value="custom"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ColorMode">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="auto"/>
<xsd:enumeration value="custom"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ContentType">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="ST_DiagramLayout">
<xsd:restriction base="xsd:integer">
<xsd:enumeration value="0"/>
<xsd:enumeration value="1"/>
<xsd:enumeration value="2"/>
<xsd:enumeration value="3"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ExtrusionType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="perspective"/>
<xsd:enumeration value="parallel"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ExtrusionRender">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="solid"/>
<xsd:enumeration value="wireFrame"/>
<xsd:enumeration value="boundingCube"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ExtrusionPlane">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="XY"/>
<xsd:enumeration value="ZX"/>
<xsd:enumeration value="YZ"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Angle">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="any"/>
<xsd:enumeration value="30"/>
<xsd:enumeration value="45"/>
<xsd:enumeration value="60"/>
<xsd:enumeration value="90"/>
<xsd:enumeration value="auto"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_CalloutDrop">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="ST_CalloutPlacement">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="top"/>
<xsd:enumeration value="center"/>
<xsd:enumeration value="bottom"/>
<xsd:enumeration value="user"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ConnectorType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="none"/>
<xsd:enumeration value="straight"/>
<xsd:enumeration value="elbow"/>
<xsd:enumeration value="curved"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_HrAlign">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="left"/>
<xsd:enumeration value="right"/>
<xsd:enumeration value="center"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ConnectType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="none"/>
<xsd:enumeration value="rect"/>
<xsd:enumeration value="segments"/>
<xsd:enumeration value="custom"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_OLELinkType">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="ST_OLEType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Embed"/>
<xsd:enumeration value="Link"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_OLEDrawAspect">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Content"/>
<xsd:enumeration value="Icon"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_OLEUpdateMode">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Always"/>
<xsd:enumeration value="OnCall"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_FillType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="gradientCenter"/>
<xsd:enumeration value="solid"/>
<xsd:enumeration value="pattern"/>
<xsd:enumeration value="tile"/>
<xsd:enumeration value="frame"/>
<xsd:enumeration value="gradientUnscaled"/>
<xsd:enumeration value="gradientRadial"/>
<xsd:enumeration value="gradient"/>
<xsd:enumeration value="background"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="urn:schemas-microsoft-com:office:powerpoint"
targetNamespace="urn:schemas-microsoft-com:office:powerpoint" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:element name="iscomment" type="CT_Empty"/>
<xsd:element name="textdata" type="CT_Rel"/>
<xsd:complexType name="CT_Empty"/>
<xsd:complexType name="CT_Rel">
<xsd:attribute name="id" type="xsd:string"/>
</xsd:complexType>
</xsd:schema>

View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="urn:schemas-microsoft-com:office:excel"
xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
targetNamespace="urn:schemas-microsoft-com:office:excel" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
schemaLocation="shared-commonSimpleTypes.xsd"/>
<xsd:element name="ClientData" type="CT_ClientData"/>
<xsd:complexType name="CT_ClientData">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="MoveWithCells" type="s:ST_TrueFalseBlank"/>
<xsd:element name="SizeWithCells" type="s:ST_TrueFalseBlank"/>
<xsd:element name="Anchor" type="xsd:string"/>
<xsd:element name="Locked" type="s:ST_TrueFalseBlank"/>
<xsd:element name="DefaultSize" type="s:ST_TrueFalseBlank"/>
<xsd:element name="PrintObject" type="s:ST_TrueFalseBlank"/>
<xsd:element name="Disabled" type="s:ST_TrueFalseBlank"/>
<xsd:element name="AutoFill" type="s:ST_TrueFalseBlank"/>
<xsd:element name="AutoLine" type="s:ST_TrueFalseBlank"/>
<xsd:element name="AutoPict" type="s:ST_TrueFalseBlank"/>
<xsd:element name="FmlaMacro" type="xsd:string"/>
<xsd:element name="TextHAlign" type="xsd:string"/>
<xsd:element name="TextVAlign" type="xsd:string"/>
<xsd:element name="LockText" type="s:ST_TrueFalseBlank"/>
<xsd:element name="JustLastX" type="s:ST_TrueFalseBlank"/>
<xsd:element name="SecretEdit" type="s:ST_TrueFalseBlank"/>
<xsd:element name="Default" type="s:ST_TrueFalseBlank"/>
<xsd:element name="Help" type="s:ST_TrueFalseBlank"/>
<xsd:element name="Cancel" type="s:ST_TrueFalseBlank"/>
<xsd:element name="Dismiss" type="s:ST_TrueFalseBlank"/>
<xsd:element name="Accel" type="xsd:integer"/>
<xsd:element name="Accel2" type="xsd:integer"/>
<xsd:element name="Row" type="xsd:integer"/>
<xsd:element name="Column" type="xsd:integer"/>
<xsd:element name="Visible" type="s:ST_TrueFalseBlank"/>
<xsd:element name="RowHidden" type="s:ST_TrueFalseBlank"/>
<xsd:element name="ColHidden" type="s:ST_TrueFalseBlank"/>
<xsd:element name="VTEdit" type="xsd:integer"/>
<xsd:element name="MultiLine" type="s:ST_TrueFalseBlank"/>
<xsd:element name="VScroll" type="s:ST_TrueFalseBlank"/>
<xsd:element name="ValidIds" type="s:ST_TrueFalseBlank"/>
<xsd:element name="FmlaRange" type="xsd:string"/>
<xsd:element name="WidthMin" type="xsd:integer"/>
<xsd:element name="Sel" type="xsd:integer"/>
<xsd:element name="NoThreeD2" type="s:ST_TrueFalseBlank"/>
<xsd:element name="SelType" type="xsd:string"/>
<xsd:element name="MultiSel" type="xsd:string"/>
<xsd:element name="LCT" type="xsd:string"/>
<xsd:element name="ListItem" type="xsd:string"/>
<xsd:element name="DropStyle" type="xsd:string"/>
<xsd:element name="Colored" type="s:ST_TrueFalseBlank"/>
<xsd:element name="DropLines" type="xsd:integer"/>
<xsd:element name="Checked" type="xsd:integer"/>
<xsd:element name="FmlaLink" type="xsd:string"/>
<xsd:element name="FmlaPict" type="xsd:string"/>
<xsd:element name="NoThreeD" type="s:ST_TrueFalseBlank"/>
<xsd:element name="FirstButton" type="s:ST_TrueFalseBlank"/>
<xsd:element name="FmlaGroup" type="xsd:string"/>
<xsd:element name="Val" type="xsd:integer"/>
<xsd:element name="Min" type="xsd:integer"/>
<xsd:element name="Max" type="xsd:integer"/>
<xsd:element name="Inc" type="xsd:integer"/>
<xsd:element name="Page" type="xsd:integer"/>
<xsd:element name="Horiz" type="s:ST_TrueFalseBlank"/>
<xsd:element name="Dx" type="xsd:integer"/>
<xsd:element name="MapOCX" type="s:ST_TrueFalseBlank"/>
<xsd:element name="CF" type="ST_CF"/>
<xsd:element name="Camera" type="s:ST_TrueFalseBlank"/>
<xsd:element name="RecalcAlways" type="s:ST_TrueFalseBlank"/>
<xsd:element name="AutoScale" type="s:ST_TrueFalseBlank"/>
<xsd:element name="DDE" type="s:ST_TrueFalseBlank"/>
<xsd:element name="UIObj" type="s:ST_TrueFalseBlank"/>
<xsd:element name="ScriptText" type="xsd:string"/>
<xsd:element name="ScriptExtended" type="xsd:string"/>
<xsd:element name="ScriptLanguage" type="xsd:nonNegativeInteger"/>
<xsd:element name="ScriptLocation" type="xsd:nonNegativeInteger"/>
<xsd:element name="FmlaTxbx" type="xsd:string"/>
</xsd:choice>
<xsd:attribute name="ObjectType" type="ST_ObjectType" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_CF">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="ST_ObjectType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Button"/>
<xsd:enumeration value="Checkbox"/>
<xsd:enumeration value="Dialog"/>
<xsd:enumeration value="Drop"/>
<xsd:enumeration value="Edit"/>
<xsd:enumeration value="GBox"/>
<xsd:enumeration value="Label"/>
<xsd:enumeration value="LineA"/>
<xsd:enumeration value="List"/>
<xsd:enumeration value="Movie"/>
<xsd:enumeration value="Note"/>
<xsd:enumeration value="Pict"/>
<xsd:enumeration value="Radio"/>
<xsd:enumeration value="RectA"/>
<xsd:enumeration value="Scroll"/>
<xsd:enumeration value="Spin"/>
<xsd:enumeration value="Shape"/>
<xsd:enumeration value="Group"/>
<xsd:enumeration value="Rect"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="urn:schemas-microsoft-com:office:word"
targetNamespace="urn:schemas-microsoft-com:office:word" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:element name="bordertop" type="CT_Border"/>
<xsd:element name="borderleft" type="CT_Border"/>
<xsd:element name="borderright" type="CT_Border"/>
<xsd:element name="borderbottom" type="CT_Border"/>
<xsd:complexType name="CT_Border">
<xsd:attribute name="type" type="ST_BorderType" use="optional"/>
<xsd:attribute name="width" type="xsd:positiveInteger" use="optional"/>
<xsd:attribute name="shadow" type="ST_BorderShadow" use="optional"/>
</xsd:complexType>
<xsd:element name="wrap" type="CT_Wrap"/>
<xsd:complexType name="CT_Wrap">
<xsd:attribute name="type" type="ST_WrapType" use="optional"/>
<xsd:attribute name="side" type="ST_WrapSide" use="optional"/>
<xsd:attribute name="anchorx" type="ST_HorizontalAnchor" use="optional"/>
<xsd:attribute name="anchory" type="ST_VerticalAnchor" use="optional"/>
</xsd:complexType>
<xsd:element name="anchorlock" type="CT_AnchorLock"/>
<xsd:complexType name="CT_AnchorLock"/>
<xsd:simpleType name="ST_BorderType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="none"/>
<xsd:enumeration value="single"/>
<xsd:enumeration value="thick"/>
<xsd:enumeration value="double"/>
<xsd:enumeration value="hairline"/>
<xsd:enumeration value="dot"/>
<xsd:enumeration value="dash"/>
<xsd:enumeration value="dotDash"/>
<xsd:enumeration value="dashDotDot"/>
<xsd:enumeration value="triple"/>
<xsd:enumeration value="thinThickSmall"/>
<xsd:enumeration value="thickThinSmall"/>
<xsd:enumeration value="thickBetweenThinSmall"/>
<xsd:enumeration value="thinThick"/>
<xsd:enumeration value="thickThin"/>
<xsd:enumeration value="thickBetweenThin"/>
<xsd:enumeration value="thinThickLarge"/>
<xsd:enumeration value="thickThinLarge"/>
<xsd:enumeration value="thickBetweenThinLarge"/>
<xsd:enumeration value="wave"/>
<xsd:enumeration value="doubleWave"/>
<xsd:enumeration value="dashedSmall"/>
<xsd:enumeration value="dashDotStroked"/>
<xsd:enumeration value="threeDEmboss"/>
<xsd:enumeration value="threeDEngrave"/>
<xsd:enumeration value="HTMLOutset"/>
<xsd:enumeration value="HTMLInset"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_BorderShadow">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="t"/>
<xsd:enumeration value="true"/>
<xsd:enumeration value="f"/>
<xsd:enumeration value="false"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_WrapType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="topAndBottom"/>
<xsd:enumeration value="square"/>
<xsd:enumeration value="none"/>
<xsd:enumeration value="tight"/>
<xsd:enumeration value="through"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_WrapSide">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="both"/>
<xsd:enumeration value="left"/>
<xsd:enumeration value="right"/>
<xsd:enumeration value="largest"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_HorizontalAnchor">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="margin"/>
<xsd:enumeration value="page"/>
<xsd:enumeration value="text"/>
<xsd:enumeration value="char"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_VerticalAnchor">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="margin"/>
<xsd:enumeration value="page"/>
<xsd:enumeration value="text"/>
<xsd:enumeration value="line"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,116 @@
<?xml version='1.0'?>
<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema" xml:lang="en">
<xs:annotation>
<xs:documentation>
See http://www.w3.org/XML/1998/namespace.html and
http://www.w3.org/TR/REC-xml for information about this namespace.
This schema document describes the XML namespace, in a form
suitable for import by other schema documents.
Note that local names in this namespace are intended to be defined
only by the World Wide Web Consortium or its subgroups. The
following names are currently defined in this namespace and should
not be used with conflicting semantics by any Working Group,
specification, or document instance:
base (as an attribute name): denotes an attribute whose value
provides a URI to be used as the base for interpreting any
relative URIs in the scope of the element on which it
appears; its value is inherited. This name is reserved
by virtue of its definition in the XML Base specification.
lang (as an attribute name): denotes an attribute whose value
is a language code for the natural language of the content of
any element; its value is inherited. This name is reserved
by virtue of its definition in the XML specification.
space (as an attribute name): denotes an attribute whose
value is a keyword indicating what whitespace processing
discipline is intended for the content of the element; its
value is inherited. This name is reserved by virtue of its
definition in the XML specification.
Father (in any context at all): denotes Jon Bosak, the chair of
the original XML Working Group. This name is reserved by
the following decision of the W3C XML Plenary and
XML Coordination groups:
In appreciation for his vision, leadership and dedication
the W3C XML Plenary on this 10th day of February, 2000
reserves for Jon Bosak in perpetuity the XML name
xml:Father
</xs:documentation>
</xs:annotation>
<xs:annotation>
<xs:documentation>This schema defines attributes and an attribute group
suitable for use by
schemas wishing to allow xml:base, xml:lang or xml:space attributes
on elements they define.
To enable this, such a schema must import this schema
for the XML namespace, e.g. as follows:
&lt;schema . . .>
. . .
&lt;import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="http://www.w3.org/2001/03/xml.xsd"/>
Subsequently, qualified reference to any of the attributes
or the group defined below will have the desired effect, e.g.
&lt;type . . .>
. . .
&lt;attributeGroup ref="xml:specialAttrs"/>
will define a type which will schema-validate an instance
element with any of those attributes</xs:documentation>
</xs:annotation>
<xs:annotation>
<xs:documentation>In keeping with the XML Schema WG's standard versioning
policy, this schema document will persist at
http://www.w3.org/2001/03/xml.xsd.
At the date of issue it can also be found at
http://www.w3.org/2001/xml.xsd.
The schema document at that URI may however change in the future,
in order to remain compatible with the latest version of XML Schema
itself. In other words, if the XML Schema namespace changes, the version
of this document at
http://www.w3.org/2001/xml.xsd will change
accordingly; the version at
http://www.w3.org/2001/03/xml.xsd will not change.
</xs:documentation>
</xs:annotation>
<xs:attribute name="lang" type="xs:language">
<xs:annotation>
<xs:documentation>In due course, we should install the relevant ISO 2- and 3-letter
codes as the enumerated possible values . . .</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="space" default="preserve">
<xs:simpleType>
<xs:restriction base="xs:NCName">
<xs:enumeration value="default"/>
<xs:enumeration value="preserve"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="base" type="xs:anyURI">
<xs:annotation>
<xs:documentation>See http://www.w3.org/TR/xmlbase/ for
information about this attribute.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributeGroup name="specialAttrs">
<xs:attribute ref="xml:base"/>
<xs:attribute ref="xml:lang"/>
<xs:attribute ref="xml:space"/>
</xs:attributeGroup>
</xs:schema>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns="http://schemas.openxmlformats.org/package/2006/content-types"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://schemas.openxmlformats.org/package/2006/content-types"
elementFormDefault="qualified" attributeFormDefault="unqualified" blockDefault="#all">
<xs:element name="Types" type="CT_Types"/>
<xs:element name="Default" type="CT_Default"/>
<xs:element name="Override" type="CT_Override"/>
<xs:complexType name="CT_Types">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="Default"/>
<xs:element ref="Override"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="CT_Default">
<xs:attribute name="Extension" type="ST_Extension" use="required"/>
<xs:attribute name="ContentType" type="ST_ContentType" use="required"/>
</xs:complexType>
<xs:complexType name="CT_Override">
<xs:attribute name="ContentType" type="ST_ContentType" use="required"/>
<xs:attribute name="PartName" type="xs:anyURI" use="required"/>
</xs:complexType>
<xs:simpleType name="ST_ContentType">
<xs:restriction base="xs:string">
<xs:pattern
value="(((([\p{IsBasicLatin}-[\p{Cc}&#127;\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+))/((([\p{IsBasicLatin}-[\p{Cc}&#127;\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+))((\s+)*;(\s+)*(((([\p{IsBasicLatin}-[\p{Cc}&#127;\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+))=((([\p{IsBasicLatin}-[\p{Cc}&#127;\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+)|(&quot;(([\p{IsLatin-1Supplement}\p{IsBasicLatin}-[\p{Cc}&#127;&quot;\n\r]]|(\s+))|(\\[\p{IsBasicLatin}]))*&quot;))))*)"
/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ST_Extension">
<xs:restriction base="xs:string">
<xs:pattern
value="([!$&amp;'\(\)\*\+,:=]|(%[0-9a-fA-F][0-9a-fA-F])|[:@]|[a-zA-Z0-9\-_~])+"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
xmlns="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" blockDefault="#all">
<xs:import namespace="http://purl.org/dc/elements/1.1/"
schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd"/>
<xs:import namespace="http://purl.org/dc/terms/"
schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd"/>
<xs:import id="xml" namespace="http://www.w3.org/XML/1998/namespace"/>
<xs:element name="coreProperties" type="CT_CoreProperties"/>
<xs:complexType name="CT_CoreProperties">
<xs:all>
<xs:element name="category" minOccurs="0" maxOccurs="1" type="xs:string"/>
<xs:element name="contentStatus" minOccurs="0" maxOccurs="1" type="xs:string"/>
<xs:element ref="dcterms:created" minOccurs="0" maxOccurs="1"/>
<xs:element ref="dc:creator" minOccurs="0" maxOccurs="1"/>
<xs:element ref="dc:description" minOccurs="0" maxOccurs="1"/>
<xs:element ref="dc:identifier" minOccurs="0" maxOccurs="1"/>
<xs:element name="keywords" minOccurs="0" maxOccurs="1" type="CT_Keywords"/>
<xs:element ref="dc:language" minOccurs="0" maxOccurs="1"/>
<xs:element name="lastModifiedBy" minOccurs="0" maxOccurs="1" type="xs:string"/>
<xs:element name="lastPrinted" minOccurs="0" maxOccurs="1" type="xs:dateTime"/>
<xs:element ref="dcterms:modified" minOccurs="0" maxOccurs="1"/>
<xs:element name="revision" minOccurs="0" maxOccurs="1" type="xs:string"/>
<xs:element ref="dc:subject" minOccurs="0" maxOccurs="1"/>
<xs:element ref="dc:title" minOccurs="0" maxOccurs="1"/>
<xs:element name="version" minOccurs="0" maxOccurs="1" type="xs:string"/>
</xs:all>
</xs:complexType>
<xs:complexType name="CT_Keywords" mixed="true">
<xs:sequence>
<xs:element name="value" minOccurs="0" maxOccurs="unbounded" type="CT_Keyword"/>
</xs:sequence>
<xs:attribute ref="xml:lang" use="optional"/>
</xs:complexType>
<xs:complexType name="CT_Keyword">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute ref="xml:lang" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://schemas.openxmlformats.org/package/2006/digital-signature"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://schemas.openxmlformats.org/package/2006/digital-signature"
elementFormDefault="qualified" attributeFormDefault="unqualified" blockDefault="#all">
<xsd:element name="SignatureTime" type="CT_SignatureTime"/>
<xsd:element name="RelationshipReference" type="CT_RelationshipReference"/>
<xsd:element name="RelationshipsGroupReference" type="CT_RelationshipsGroupReference"/>
<xsd:complexType name="CT_SignatureTime">
<xsd:sequence>
<xsd:element name="Format" type="ST_Format"/>
<xsd:element name="Value" type="ST_Value"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_RelationshipReference">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="SourceId" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="CT_RelationshipsGroupReference">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="SourceType" type="xsd:anyURI" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:simpleType name="ST_Format">
<xsd:restriction base="xsd:string">
<xsd:pattern
value="(YYYY)|(YYYY-MM)|(YYYY-MM-DD)|(YYYY-MM-DDThh:mmTZD)|(YYYY-MM-DDThh:mm:ssTZD)|(YYYY-MM-DDThh:mm:ss.sTZD)"
/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Value">
<xsd:restriction base="xsd:string">
<xsd:pattern
value="(([0-9][0-9][0-9][0-9]))|(([0-9][0-9][0-9][0-9])-((0[1-9])|(1(0|1|2))))|(([0-9][0-9][0-9][0-9])-((0[1-9])|(1(0|1|2)))-((0[1-9])|(1[0-9])|(2[0-9])|(3(0|1))))|(([0-9][0-9][0-9][0-9])-((0[1-9])|(1(0|1|2)))-((0[1-9])|(1[0-9])|(2[0-9])|(3(0|1)))T((0[0-9])|(1[0-9])|(2(0|1|2|3))):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9]))(((\+|-)((0[0-9])|(1[0-9])|(2(0|1|2|3))):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9])))|Z))|(([0-9][0-9][0-9][0-9])-((0[1-9])|(1(0|1|2)))-((0[1-9])|(1[0-9])|(2[0-9])|(3(0|1)))T((0[0-9])|(1[0-9])|(2(0|1|2|3))):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9])):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9]))(((\+|-)((0[0-9])|(1[0-9])|(2(0|1|2|3))):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9])))|Z))|(([0-9][0-9][0-9][0-9])-((0[1-9])|(1(0|1|2)))-((0[1-9])|(1[0-9])|(2[0-9])|(3(0|1)))T((0[0-9])|(1[0-9])|(2(0|1|2|3))):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9])):(((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9]))\.[0-9])(((\+|-)((0[0-9])|(1[0-9])|(2(0|1|2|3))):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9])))|Z))"
/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://schemas.openxmlformats.org/package/2006/relationships"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://schemas.openxmlformats.org/package/2006/relationships"
elementFormDefault="qualified" attributeFormDefault="unqualified" blockDefault="#all">
<xsd:element name="Relationships" type="CT_Relationships"/>
<xsd:element name="Relationship" type="CT_Relationship"/>
<xsd:complexType name="CT_Relationships">
<xsd:sequence>
<xsd:element ref="Relationship" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Relationship">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="TargetMode" type="ST_TargetMode" use="optional"/>
<xsd:attribute name="Target" type="xsd:anyURI" use="required"/>
<xsd:attribute name="Type" type="xsd:anyURI" use="required"/>
<xsd:attribute name="Id" type="xsd:ID" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:simpleType name="ST_TargetMode">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="External"/>
<xsd:enumeration value="Internal"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
attributeFormDefault="unqualified" elementFormDefault="qualified"
targetNamespace="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!--
This XSD is a modified version of the one found at:
https://github.com/plutext/docx4j/blob/master/xsd/mce/markup-compatibility-2006-MINIMAL.xsd
This XSD has 2 objectives:
1. round tripping @mc:Ignorable
<w:document
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
mc:Ignorable="w14 w15 wp14">
2. enabling AlternateContent to be manipulated in certain elements
(in the unusual case where the content model is xsd:any, it doesn't have to be explicitly added)
See further ECMA-376, 4th Edition, Office Open XML File Formats
Part 3 : Markup Compatibility and Extensibility
-->
<!-- Objective 1 -->
<xsd:attribute name="Ignorable" type="xsd:string" />
<!-- Objective 2 -->
<xsd:attribute name="MustUnderstand" type="xsd:string" />
<xsd:attribute name="ProcessContent" type="xsd:string" />
<!-- An AlternateContent element shall contain one or more Choice child elements, optionally followed by a
Fallback child element. If present, there shall be only one Fallback element, and it shall follow all Choice
elements. -->
<xsd:element name="AlternateContent">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Choice" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded"
processContents="strict">
</xsd:any>
</xsd:sequence>
<xsd:attribute name="Requires" type="xsd:string" use="required" />
<xsd:attribute ref="mc:Ignorable" use="optional" />
<xsd:attribute ref="mc:MustUnderstand" use="optional" />
<xsd:attribute ref="mc:ProcessContent" use="optional" />
</xsd:complexType>
</xsd:element>
<xsd:element name="Fallback" minOccurs="0" maxOccurs="1">
<xsd:complexType>
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded"
processContents="strict">
</xsd:any>
</xsd:sequence>
<xsd:attribute ref="mc:Ignorable" use="optional" />
<xsd:attribute ref="mc:MustUnderstand" use="optional" />
<xsd:attribute ref="mc:ProcessContent" use="optional" />
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<!-- AlternateContent elements might include the attributes Ignorable,
MustUnderstand and ProcessContent described in this Part of ECMA-376. These
attributes qualified names shall be prefixed when associated with an AlternateContent
element. -->
<xsd:attribute ref="mc:Ignorable" use="optional" />
<xsd:attribute ref="mc:MustUnderstand" use="optional" />
<xsd:attribute ref="mc:ProcessContent" use="optional" />
</xsd:complexType>
</xsd:element>
</xsd:schema>

View File

@@ -0,0 +1,560 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns="http://schemas.microsoft.com/office/word/2010/wordml" targetNamespace="http://schemas.microsoft.com/office/word/2010/wordml">
<!-- <xsd:import id="rel" namespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships" schemaLocation="orel.xsd"/> -->
<xsd:import id="w" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<!-- <xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main" schemaLocation="oartbasetypes.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main" schemaLocation="oartsplineproperties.xsd"/> -->
<xsd:complexType name="CT_LongHexNumber">
<xsd:attribute name="val" type="w:ST_LongHexNumber" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_OnOff">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="true"/>
<xsd:enumeration value="false"/>
<xsd:enumeration value="0"/>
<xsd:enumeration value="1"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_OnOff">
<xsd:attribute name="val" type="ST_OnOff"/>
</xsd:complexType>
<xsd:element name="docId" type="CT_LongHexNumber"/>
<xsd:element name="conflictMode" type="CT_OnOff"/>
<xsd:attributeGroup name="AG_Parids">
<xsd:attribute name="paraId" type="w:ST_LongHexNumber"/>
<xsd:attribute name="textId" type="w:ST_LongHexNumber"/>
</xsd:attributeGroup>
<xsd:attribute name="anchorId" type="w:ST_LongHexNumber"/>
<xsd:attribute name="noSpellErr" type="ST_OnOff"/>
<xsd:element name="customXmlConflictInsRangeStart" type="w:CT_TrackChange"/>
<xsd:element name="customXmlConflictInsRangeEnd" type="w:CT_Markup"/>
<xsd:element name="customXmlConflictDelRangeStart" type="w:CT_TrackChange"/>
<xsd:element name="customXmlConflictDelRangeEnd" type="w:CT_Markup"/>
<xsd:group name="EG_RunLevelConflicts">
<xsd:sequence>
<xsd:element name="conflictIns" type="w:CT_RunTrackChange" minOccurs="0"/>
<xsd:element name="conflictDel" type="w:CT_RunTrackChange" minOccurs="0"/>
</xsd:sequence>
</xsd:group>
<xsd:group name="EG_Conflicts">
<xsd:choice>
<xsd:element name="conflictIns" type="w:CT_TrackChange" minOccurs="0"/>
<xsd:element name="conflictDel" type="w:CT_TrackChange" minOccurs="0"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_Percentage">
<xsd:attribute name="val" type="a:ST_Percentage" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_PositiveFixedPercentage">
<xsd:attribute name="val" type="a:ST_PositiveFixedPercentage" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_PositivePercentage">
<xsd:attribute name="val" type="a:ST_PositivePercentage" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_SchemeColorVal">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="bg1"/>
<xsd:enumeration value="tx1"/>
<xsd:enumeration value="bg2"/>
<xsd:enumeration value="tx2"/>
<xsd:enumeration value="accent1"/>
<xsd:enumeration value="accent2"/>
<xsd:enumeration value="accent3"/>
<xsd:enumeration value="accent4"/>
<xsd:enumeration value="accent5"/>
<xsd:enumeration value="accent6"/>
<xsd:enumeration value="hlink"/>
<xsd:enumeration value="folHlink"/>
<xsd:enumeration value="dk1"/>
<xsd:enumeration value="lt1"/>
<xsd:enumeration value="dk2"/>
<xsd:enumeration value="lt2"/>
<xsd:enumeration value="phClr"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_RectAlignment">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="none"/>
<xsd:enumeration value="tl"/>
<xsd:enumeration value="t"/>
<xsd:enumeration value="tr"/>
<xsd:enumeration value="l"/>
<xsd:enumeration value="ctr"/>
<xsd:enumeration value="r"/>
<xsd:enumeration value="bl"/>
<xsd:enumeration value="b"/>
<xsd:enumeration value="br"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_PathShadeType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="shape"/>
<xsd:enumeration value="circle"/>
<xsd:enumeration value="rect"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_LineCap">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="rnd"/>
<xsd:enumeration value="sq"/>
<xsd:enumeration value="flat"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_PresetLineDashVal">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="solid"/>
<xsd:enumeration value="dot"/>
<xsd:enumeration value="sysDot"/>
<xsd:enumeration value="dash"/>
<xsd:enumeration value="sysDash"/>
<xsd:enumeration value="lgDash"/>
<xsd:enumeration value="dashDot"/>
<xsd:enumeration value="sysDashDot"/>
<xsd:enumeration value="lgDashDot"/>
<xsd:enumeration value="lgDashDotDot"/>
<xsd:enumeration value="sysDashDotDot"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_PenAlignment">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="ctr"/>
<xsd:enumeration value="in"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_CompoundLine">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="sng"/>
<xsd:enumeration value="dbl"/>
<xsd:enumeration value="thickThin"/>
<xsd:enumeration value="thinThick"/>
<xsd:enumeration value="tri"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_RelativeRect">
<xsd:attribute name="l" use="optional" type="a:ST_Percentage"/>
<xsd:attribute name="t" use="optional" type="a:ST_Percentage"/>
<xsd:attribute name="r" use="optional" type="a:ST_Percentage"/>
<xsd:attribute name="b" use="optional" type="a:ST_Percentage"/>
</xsd:complexType>
<xsd:group name="EG_ColorTransform">
<xsd:choice>
<xsd:element name="tint" type="CT_PositiveFixedPercentage"/>
<xsd:element name="shade" type="CT_PositiveFixedPercentage"/>
<xsd:element name="alpha" type="CT_PositiveFixedPercentage"/>
<xsd:element name="hueMod" type="CT_PositivePercentage"/>
<xsd:element name="sat" type="CT_Percentage"/>
<xsd:element name="satOff" type="CT_Percentage"/>
<xsd:element name="satMod" type="CT_Percentage"/>
<xsd:element name="lum" type="CT_Percentage"/>
<xsd:element name="lumOff" type="CT_Percentage"/>
<xsd:element name="lumMod" type="CT_Percentage"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_SRgbColor">
<xsd:sequence>
<xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="val" type="s:ST_HexColorRGB" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_SchemeColor">
<xsd:sequence>
<xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="val" type="ST_SchemeColorVal" use="required"/>
</xsd:complexType>
<xsd:group name="EG_ColorChoice">
<xsd:choice>
<xsd:element name="srgbClr" type="CT_SRgbColor"/>
<xsd:element name="schemeClr" type="CT_SchemeColor"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_Color">
<xsd:sequence>
<xsd:group ref="EG_ColorChoice"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GradientStop">
<xsd:sequence>
<xsd:group ref="EG_ColorChoice"/>
</xsd:sequence>
<xsd:attribute name="pos" type="a:ST_PositiveFixedPercentage" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_GradientStopList">
<xsd:sequence>
<xsd:element name="gs" type="CT_GradientStop" minOccurs="2" maxOccurs="10"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_LinearShadeProperties">
<xsd:attribute name="ang" type="a:ST_PositiveFixedAngle" use="optional"/>
<xsd:attribute name="scaled" type="ST_OnOff" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_PathShadeProperties">
<xsd:sequence>
<xsd:element name="fillToRect" type="CT_RelativeRect" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="path" type="ST_PathShadeType" use="optional"/>
</xsd:complexType>
<xsd:group name="EG_ShadeProperties">
<xsd:choice>
<xsd:element name="lin" type="CT_LinearShadeProperties"/>
<xsd:element name="path" type="CT_PathShadeProperties"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_SolidColorFillProperties">
<xsd:sequence>
<xsd:group ref="EG_ColorChoice" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GradientFillProperties">
<xsd:sequence>
<xsd:element name="gsLst" type="CT_GradientStopList" minOccurs="0"/>
<xsd:group ref="EG_ShadeProperties" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_FillProperties">
<xsd:choice>
<xsd:element name="noFill" type="w:CT_Empty"/>
<xsd:element name="solidFill" type="CT_SolidColorFillProperties"/>
<xsd:element name="gradFill" type="CT_GradientFillProperties"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_PresetLineDashProperties">
<xsd:attribute name="val" type="ST_PresetLineDashVal" use="optional"/>
</xsd:complexType>
<xsd:group name="EG_LineDashProperties">
<xsd:choice>
<xsd:element name="prstDash" type="CT_PresetLineDashProperties"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_LineJoinMiterProperties">
<xsd:attribute name="lim" type="a:ST_PositivePercentage" use="optional"/>
</xsd:complexType>
<xsd:group name="EG_LineJoinProperties">
<xsd:choice>
<xsd:element name="round" type="w:CT_Empty"/>
<xsd:element name="bevel" type="w:CT_Empty"/>
<xsd:element name="miter" type="CT_LineJoinMiterProperties"/>
</xsd:choice>
</xsd:group>
<xsd:simpleType name="ST_PresetCameraType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="legacyObliqueTopLeft"/>
<xsd:enumeration value="legacyObliqueTop"/>
<xsd:enumeration value="legacyObliqueTopRight"/>
<xsd:enumeration value="legacyObliqueLeft"/>
<xsd:enumeration value="legacyObliqueFront"/>
<xsd:enumeration value="legacyObliqueRight"/>
<xsd:enumeration value="legacyObliqueBottomLeft"/>
<xsd:enumeration value="legacyObliqueBottom"/>
<xsd:enumeration value="legacyObliqueBottomRight"/>
<xsd:enumeration value="legacyPerspectiveTopLeft"/>
<xsd:enumeration value="legacyPerspectiveTop"/>
<xsd:enumeration value="legacyPerspectiveTopRight"/>
<xsd:enumeration value="legacyPerspectiveLeft"/>
<xsd:enumeration value="legacyPerspectiveFront"/>
<xsd:enumeration value="legacyPerspectiveRight"/>
<xsd:enumeration value="legacyPerspectiveBottomLeft"/>
<xsd:enumeration value="legacyPerspectiveBottom"/>
<xsd:enumeration value="legacyPerspectiveBottomRight"/>
<xsd:enumeration value="orthographicFront"/>
<xsd:enumeration value="isometricTopUp"/>
<xsd:enumeration value="isometricTopDown"/>
<xsd:enumeration value="isometricBottomUp"/>
<xsd:enumeration value="isometricBottomDown"/>
<xsd:enumeration value="isometricLeftUp"/>
<xsd:enumeration value="isometricLeftDown"/>
<xsd:enumeration value="isometricRightUp"/>
<xsd:enumeration value="isometricRightDown"/>
<xsd:enumeration value="isometricOffAxis1Left"/>
<xsd:enumeration value="isometricOffAxis1Right"/>
<xsd:enumeration value="isometricOffAxis1Top"/>
<xsd:enumeration value="isometricOffAxis2Left"/>
<xsd:enumeration value="isometricOffAxis2Right"/>
<xsd:enumeration value="isometricOffAxis2Top"/>
<xsd:enumeration value="isometricOffAxis3Left"/>
<xsd:enumeration value="isometricOffAxis3Right"/>
<xsd:enumeration value="isometricOffAxis3Bottom"/>
<xsd:enumeration value="isometricOffAxis4Left"/>
<xsd:enumeration value="isometricOffAxis4Right"/>
<xsd:enumeration value="isometricOffAxis4Bottom"/>
<xsd:enumeration value="obliqueTopLeft"/>
<xsd:enumeration value="obliqueTop"/>
<xsd:enumeration value="obliqueTopRight"/>
<xsd:enumeration value="obliqueLeft"/>
<xsd:enumeration value="obliqueRight"/>
<xsd:enumeration value="obliqueBottomLeft"/>
<xsd:enumeration value="obliqueBottom"/>
<xsd:enumeration value="obliqueBottomRight"/>
<xsd:enumeration value="perspectiveFront"/>
<xsd:enumeration value="perspectiveLeft"/>
<xsd:enumeration value="perspectiveRight"/>
<xsd:enumeration value="perspectiveAbove"/>
<xsd:enumeration value="perspectiveBelow"/>
<xsd:enumeration value="perspectiveAboveLeftFacing"/>
<xsd:enumeration value="perspectiveAboveRightFacing"/>
<xsd:enumeration value="perspectiveContrastingLeftFacing"/>
<xsd:enumeration value="perspectiveContrastingRightFacing"/>
<xsd:enumeration value="perspectiveHeroicLeftFacing"/>
<xsd:enumeration value="perspectiveHeroicRightFacing"/>
<xsd:enumeration value="perspectiveHeroicExtremeLeftFacing"/>
<xsd:enumeration value="perspectiveHeroicExtremeRightFacing"/>
<xsd:enumeration value="perspectiveRelaxed"/>
<xsd:enumeration value="perspectiveRelaxedModerately"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Camera">
<xsd:attribute name="prst" use="required" type="ST_PresetCameraType"/>
</xsd:complexType>
<xsd:complexType name="CT_SphereCoords">
<xsd:attribute name="lat" type="a:ST_PositiveFixedAngle" use="required"/>
<xsd:attribute name="lon" type="a:ST_PositiveFixedAngle" use="required"/>
<xsd:attribute name="rev" type="a:ST_PositiveFixedAngle" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_LightRigType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="legacyFlat1"/>
<xsd:enumeration value="legacyFlat2"/>
<xsd:enumeration value="legacyFlat3"/>
<xsd:enumeration value="legacyFlat4"/>
<xsd:enumeration value="legacyNormal1"/>
<xsd:enumeration value="legacyNormal2"/>
<xsd:enumeration value="legacyNormal3"/>
<xsd:enumeration value="legacyNormal4"/>
<xsd:enumeration value="legacyHarsh1"/>
<xsd:enumeration value="legacyHarsh2"/>
<xsd:enumeration value="legacyHarsh3"/>
<xsd:enumeration value="legacyHarsh4"/>
<xsd:enumeration value="threePt"/>
<xsd:enumeration value="balanced"/>
<xsd:enumeration value="soft"/>
<xsd:enumeration value="harsh"/>
<xsd:enumeration value="flood"/>
<xsd:enumeration value="contrasting"/>
<xsd:enumeration value="morning"/>
<xsd:enumeration value="sunrise"/>
<xsd:enumeration value="sunset"/>
<xsd:enumeration value="chilly"/>
<xsd:enumeration value="freezing"/>
<xsd:enumeration value="flat"/>
<xsd:enumeration value="twoPt"/>
<xsd:enumeration value="glow"/>
<xsd:enumeration value="brightRoom"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_LightRigDirection">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="tl"/>
<xsd:enumeration value="t"/>
<xsd:enumeration value="tr"/>
<xsd:enumeration value="l"/>
<xsd:enumeration value="r"/>
<xsd:enumeration value="bl"/>
<xsd:enumeration value="b"/>
<xsd:enumeration value="br"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_LightRig">
<xsd:sequence>
<xsd:element name="rot" type="CT_SphereCoords" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="rig" type="ST_LightRigType" use="required"/>
<xsd:attribute name="dir" type="ST_LightRigDirection" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_BevelPresetType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="relaxedInset"/>
<xsd:enumeration value="circle"/>
<xsd:enumeration value="slope"/>
<xsd:enumeration value="cross"/>
<xsd:enumeration value="angle"/>
<xsd:enumeration value="softRound"/>
<xsd:enumeration value="convex"/>
<xsd:enumeration value="coolSlant"/>
<xsd:enumeration value="divot"/>
<xsd:enumeration value="riblet"/>
<xsd:enumeration value="hardEdge"/>
<xsd:enumeration value="artDeco"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Bevel">
<xsd:attribute name="w" type="a:ST_PositiveCoordinate" use="optional"/>
<xsd:attribute name="h" type="a:ST_PositiveCoordinate" use="optional"/>
<xsd:attribute name="prst" type="ST_BevelPresetType" use="optional"/>
</xsd:complexType>
<xsd:simpleType name="ST_PresetMaterialType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="legacyMatte"/>
<xsd:enumeration value="legacyPlastic"/>
<xsd:enumeration value="legacyMetal"/>
<xsd:enumeration value="legacyWireframe"/>
<xsd:enumeration value="matte"/>
<xsd:enumeration value="plastic"/>
<xsd:enumeration value="metal"/>
<xsd:enumeration value="warmMatte"/>
<xsd:enumeration value="translucentPowder"/>
<xsd:enumeration value="powder"/>
<xsd:enumeration value="dkEdge"/>
<xsd:enumeration value="softEdge"/>
<xsd:enumeration value="clear"/>
<xsd:enumeration value="flat"/>
<xsd:enumeration value="softmetal"/>
<xsd:enumeration value="none"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Glow">
<xsd:sequence>
<xsd:group ref="EG_ColorChoice"/>
</xsd:sequence>
<xsd:attribute name="rad" use="optional" type="a:ST_PositiveCoordinate"/>
</xsd:complexType>
<xsd:complexType name="CT_Shadow">
<xsd:sequence>
<xsd:group ref="EG_ColorChoice"/>
</xsd:sequence>
<xsd:attribute name="blurRad" use="optional" type="a:ST_PositiveCoordinate"/>
<xsd:attribute name="dist" use="optional" type="a:ST_PositiveCoordinate"/>
<xsd:attribute name="dir" use="optional" type="a:ST_PositiveFixedAngle"/>
<xsd:attribute name="sx" use="optional" type="a:ST_Percentage"/>
<xsd:attribute name="sy" use="optional" type="a:ST_Percentage"/>
<xsd:attribute name="kx" use="optional" type="a:ST_FixedAngle"/>
<xsd:attribute name="ky" use="optional" type="a:ST_FixedAngle"/>
<xsd:attribute name="algn" use="optional" type="ST_RectAlignment"/>
</xsd:complexType>
<xsd:complexType name="CT_Reflection">
<xsd:attribute name="blurRad" use="optional" type="a:ST_PositiveCoordinate"/>
<xsd:attribute name="stA" use="optional" type="a:ST_PositiveFixedPercentage"/>
<xsd:attribute name="stPos" use="optional" type="a:ST_PositiveFixedPercentage"/>
<xsd:attribute name="endA" use="optional" type="a:ST_PositiveFixedPercentage"/>
<xsd:attribute name="endPos" use="optional" type="a:ST_PositiveFixedPercentage"/>
<xsd:attribute name="dist" use="optional" type="a:ST_PositiveCoordinate"/>
<xsd:attribute name="dir" use="optional" type="a:ST_PositiveFixedAngle"/>
<xsd:attribute name="fadeDir" use="optional" type="a:ST_PositiveFixedAngle"/>
<xsd:attribute name="sx" use="optional" type="a:ST_Percentage"/>
<xsd:attribute name="sy" use="optional" type="a:ST_Percentage"/>
<xsd:attribute name="kx" use="optional" type="a:ST_FixedAngle"/>
<xsd:attribute name="ky" use="optional" type="a:ST_FixedAngle"/>
<xsd:attribute name="algn" use="optional" type="ST_RectAlignment"/>
</xsd:complexType>
<xsd:complexType name="CT_FillTextEffect">
<xsd:sequence>
<xsd:group ref="EG_FillProperties" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TextOutlineEffect">
<xsd:sequence>
<xsd:group ref="EG_FillProperties" minOccurs="0"/>
<xsd:group ref="EG_LineDashProperties" minOccurs="0"/>
<xsd:group ref="EG_LineJoinProperties" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="w" use="optional" type="a:ST_LineWidth"/>
<xsd:attribute name="cap" use="optional" type="ST_LineCap"/>
<xsd:attribute name="cmpd" use="optional" type="ST_CompoundLine"/>
<xsd:attribute name="algn" use="optional" type="ST_PenAlignment"/>
</xsd:complexType>
<xsd:complexType name="CT_Scene3D">
<xsd:sequence>
<xsd:element name="camera" type="CT_Camera"/>
<xsd:element name="lightRig" type="CT_LightRig"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Props3D">
<xsd:sequence>
<xsd:element name="bevelT" type="CT_Bevel" minOccurs="0"/>
<xsd:element name="bevelB" type="CT_Bevel" minOccurs="0"/>
<xsd:element name="extrusionClr" type="CT_Color" minOccurs="0"/>
<xsd:element name="contourClr" type="CT_Color" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="extrusionH" type="a:ST_PositiveCoordinate" use="optional"/>
<xsd:attribute name="contourW" type="a:ST_PositiveCoordinate" use="optional"/>
<xsd:attribute name="prstMaterial" type="ST_PresetMaterialType" use="optional"/>
</xsd:complexType>
<xsd:group name="EG_RPrTextEffects">
<xsd:sequence>
<xsd:element name="glow" minOccurs="0" type="CT_Glow"/>
<xsd:element name="shadow" minOccurs="0" type="CT_Shadow"/>
<xsd:element name="reflection" minOccurs="0" type="CT_Reflection"/>
<xsd:element name="textOutline" minOccurs="0" type="CT_TextOutlineEffect"/>
<xsd:element name="textFill" minOccurs="0" type="CT_FillTextEffect"/>
<xsd:element name="scene3d" minOccurs="0" type="CT_Scene3D"/>
<xsd:element name="props3d" minOccurs="0" type="CT_Props3D"/>
</xsd:sequence>
</xsd:group>
<xsd:simpleType name="ST_Ligatures">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="none"/>
<xsd:enumeration value="standard"/>
<xsd:enumeration value="contextual"/>
<xsd:enumeration value="historical"/>
<xsd:enumeration value="discretional"/>
<xsd:enumeration value="standardContextual"/>
<xsd:enumeration value="standardHistorical"/>
<xsd:enumeration value="contextualHistorical"/>
<xsd:enumeration value="standardDiscretional"/>
<xsd:enumeration value="contextualDiscretional"/>
<xsd:enumeration value="historicalDiscretional"/>
<xsd:enumeration value="standardContextualHistorical"/>
<xsd:enumeration value="standardContextualDiscretional"/>
<xsd:enumeration value="standardHistoricalDiscretional"/>
<xsd:enumeration value="contextualHistoricalDiscretional"/>
<xsd:enumeration value="all"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Ligatures">
<xsd:attribute name="val" type="ST_Ligatures" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_NumForm">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="default"/>
<xsd:enumeration value="lining"/>
<xsd:enumeration value="oldStyle"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_NumForm">
<xsd:attribute name="val" type="ST_NumForm" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_NumSpacing">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="default"/>
<xsd:enumeration value="proportional"/>
<xsd:enumeration value="tabular"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_NumSpacing">
<xsd:attribute name="val" type="ST_NumSpacing" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_StyleSet">
<xsd:attribute name="id" type="s:ST_UnsignedDecimalNumber" use="required"/>
<xsd:attribute name="val" type="ST_OnOff" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_StylisticSets">
<xsd:sequence minOccurs="0">
<xsd:element name="styleSet" minOccurs="0" maxOccurs="unbounded" type="CT_StyleSet"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_RPrOpenType">
<xsd:sequence>
<xsd:element name="ligatures" minOccurs="0" type="CT_Ligatures"/>
<xsd:element name="numForm" minOccurs="0" type="CT_NumForm"/>
<xsd:element name="numSpacing" minOccurs="0" type="CT_NumSpacing"/>
<xsd:element name="stylisticSets" minOccurs="0" type="CT_StylisticSets"/>
<xsd:element name="cntxtAlts" minOccurs="0" type="CT_OnOff"/>
</xsd:sequence>
</xsd:group>
<xsd:element name="discardImageEditingData" type="CT_OnOff"/>
<xsd:element name="defaultImageDpi" type="CT_DefaultImageDpi"/>
<xsd:complexType name="CT_DefaultImageDpi">
<xsd:attribute name="val" type="w:ST_DecimalNumber" use="required"/>
</xsd:complexType>
<xsd:element name="entityPicker" type="w:CT_Empty"/>
<xsd:complexType name="CT_SdtCheckboxSymbol">
<xsd:attribute name="font" type="s:ST_String"/>
<xsd:attribute name="val" type="w:ST_ShortHexNumber"/>
</xsd:complexType>
<xsd:complexType name="CT_SdtCheckbox">
<xsd:sequence>
<xsd:element name="checked" type="CT_OnOff" minOccurs="0"/>
<xsd:element name="checkedState" type="CT_SdtCheckboxSymbol" minOccurs="0"/>
<xsd:element name="uncheckedState" type="CT_SdtCheckboxSymbol" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="checkbox" type="CT_SdtCheckbox"/>
</xsd:schema>

View File

@@ -0,0 +1,67 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2012/wordml" targetNamespace="http://schemas.microsoft.com/office/word/2012/wordml">
<xsd:import id="w12" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" schemaLocation="../ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd"/>
<xsd:element name="color" type="w12:CT_Color"/>
<xsd:simpleType name="ST_SdtAppearance">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="boundingBox"/>
<xsd:enumeration value="tags"/>
<xsd:enumeration value="hidden"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="dataBinding" type="w12:CT_DataBinding"/>
<xsd:complexType name="CT_SdtAppearance">
<xsd:attribute name="val" type="ST_SdtAppearance"/>
</xsd:complexType>
<xsd:element name="appearance" type="CT_SdtAppearance"/>
<xsd:complexType name="CT_CommentsEx">
<xsd:sequence>
<xsd:element name="commentEx" type="CT_CommentEx" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_CommentEx">
<xsd:attribute name="paraId" type="w12:ST_LongHexNumber" use="required"/>
<xsd:attribute name="paraIdParent" type="w12:ST_LongHexNumber" use="optional"/>
<xsd:attribute name="done" type="s:ST_OnOff" use="optional"/>
</xsd:complexType>
<xsd:element name="commentsEx" type="CT_CommentsEx"/>
<xsd:complexType name="CT_People">
<xsd:sequence>
<xsd:element name="person" type="CT_Person" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_PresenceInfo">
<xsd:attribute name="providerId" type="xsd:string" use="required"/>
<xsd:attribute name="userId" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Person">
<xsd:sequence>
<xsd:element name="presenceInfo" type="CT_PresenceInfo" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="author" type="s:ST_String" use="required"/>
</xsd:complexType>
<xsd:element name="people" type="CT_People"/>
<xsd:complexType name="CT_SdtRepeatedSection">
<xsd:sequence>
<xsd:element name="sectionTitle" type="w12:CT_String" minOccurs="0"/>
<xsd:element name="doNotAllowInsertDeleteSection" type="w12:CT_OnOff" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="ST_Guid">
<xsd:restriction base="xsd:token">
<xsd:pattern value="\{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Guid">
<xsd:attribute name="val" type="ST_Guid"/>
</xsd:complexType>
<xsd:element name="repeatingSection" type="CT_SdtRepeatedSection"/>
<xsd:element name="repeatingSectionItem" type="w12:CT_Empty"/>
<xsd:element name="chartTrackingRefBased" type="w12:CT_OnOff"/>
<xsd:element name="collapsed" type="w12:CT_OnOff"/>
<xsd:element name="docId" type="CT_Guid"/>
<xsd:element name="footnoteColumns" type="w12:CT_DecimalNumber"/>
<xsd:element name="webExtensionLinked" type="w12:CT_OnOff"/>
<xsd:element name="webExtensionCreated" type="w12:CT_OnOff"/>
<xsd:attribute name="restartNumberingAfterBreak" type="s:ST_OnOff"/>
</xsd:schema>

View File

@@ -0,0 +1,14 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2018/wordml" targetNamespace="http://schemas.microsoft.com/office/word/2018/wordml">
<xsd:import id="w12" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:complexType name="CT_Extension">
<xsd:sequence>
<xsd:any processContents="lax"/>
</xsd:sequence>
<xsd:attribute name="uri" type="xsd:token"/>
</xsd:complexType>
<xsd:complexType name="CT_ExtensionList">
<xsd:sequence>
<xsd:element name="ext" type="CT_Extension" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

View File

@@ -0,0 +1,20 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2018/wordml/cex" targetNamespace="http://schemas.microsoft.com/office/word/2018/wordml/cex">
<xsd:import id="w16" namespace="http://schemas.microsoft.com/office/word/2018/wordml" schemaLocation="wml-2018.xsd"/>
<xsd:import id="w" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:import id="s" namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" schemaLocation="../ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd"/>
<xsd:complexType name="CT_CommentsExtensible">
<xsd:sequence>
<xsd:element name="commentExtensible" type="CT_CommentExtensible" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="extLst" type="w16:CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_CommentExtensible">
<xsd:sequence>
<xsd:element name="extLst" type="w16:CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="durableId" type="w:ST_LongHexNumber" use="required"/>
<xsd:attribute name="dateUtc" type="w:ST_DateTime" use="optional"/>
<xsd:attribute name="intelligentPlaceholder" type="s:ST_OnOff" use="optional"/>
</xsd:complexType>
<xsd:element name="commentsExtensible" type="CT_CommentsExtensible"/>
</xsd:schema>

View File

@@ -0,0 +1,13 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2016/wordml/cid" targetNamespace="http://schemas.microsoft.com/office/word/2016/wordml/cid">
<xsd:import id="w12" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:complexType name="CT_CommentsIds">
<xsd:sequence>
<xsd:element name="commentId" type="CT_CommentId" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_CommentId">
<xsd:attribute name="paraId" type="w12:ST_LongHexNumber" use="required"/>
<xsd:attribute name="durableId" type="w12:ST_LongHexNumber" use="required"/>
</xsd:complexType>
<xsd:element name="commentsIds" type="CT_CommentsIds"/>
</xsd:schema>

View File

@@ -0,0 +1,4 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" targetNamespace="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash">
<xsd:import id="w12" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:attribute name="storeItemChecksum" type="w12:ST_String"/>
</xsd:schema>

View File

@@ -0,0 +1,8 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2015/wordml/symex" targetNamespace="http://schemas.microsoft.com/office/word/2015/wordml/symex">
<xsd:import id="w12" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:complexType name="CT_SymEx">
<xsd:attribute name="font" type="w12:ST_String"/>
<xsd:attribute name="char" type="w12:ST_LongHexNumber"/>
</xsd:complexType>
<xsd:element name="symEx" type="CT_SymEx"/>
</xsd:schema>

159
skills/ppt/ooxml/scripts/pack.py Executable file
View File

@@ -0,0 +1,159 @@
#!/usr/bin/env python3
"""
Tool to pack a directory into a .docx, .pptx, or .xlsx file with XML formatting undone.
Example usage:
python pack.py <input_directory> <office_file> [--force]
"""
import argparse
import shutil
import subprocess
import sys
import tempfile
import defusedxml.minidom
import zipfile
from pathlib import Path
def main():
parser = argparse.ArgumentParser(description="Pack a directory into an Office file")
parser.add_argument("input_directory", help="Unpacked Office document directory")
parser.add_argument("output_file", help="Output Office file (.docx/.pptx/.xlsx)")
parser.add_argument("--force", action="store_true", help="Skip validation")
args = parser.parse_args()
try:
success = pack_document(
args.input_directory, args.output_file, validate=not args.force
)
# Show warning if validation was skipped
if args.force:
print("Warning: Skipped validation, file may be corrupt", file=sys.stderr)
# Exit with error if validation failed
elif not success:
print("Contents would produce a corrupt file.", file=sys.stderr)
print("Please validate XML before repacking.", file=sys.stderr)
print("Use --force to skip validation and pack anyway.", file=sys.stderr)
sys.exit(1)
except ValueError as e:
sys.exit(f"Error: {e}")
def pack_document(input_dir, output_file, validate=False):
"""Pack a directory into an Office file (.docx/.pptx/.xlsx).
Args:
input_dir: Path to unpacked Office document directory
output_file: Path to output Office file
validate: If True, validates with soffice (default: False)
Returns:
bool: True if successful, False if validation failed
"""
input_dir = Path(input_dir)
output_file = Path(output_file)
if not input_dir.is_dir():
raise ValueError(f"{input_dir} is not a directory")
if output_file.suffix.lower() not in {".docx", ".pptx", ".xlsx"}:
raise ValueError(f"{output_file} must be a .docx, .pptx, or .xlsx file")
# Work in temporary directory to avoid modifying original
with tempfile.TemporaryDirectory() as temp_dir:
temp_content_dir = Path(temp_dir) / "content"
shutil.copytree(input_dir, temp_content_dir)
# Process XML files to remove pretty-printing whitespace
for pattern in ["*.xml", "*.rels"]:
for xml_file in temp_content_dir.rglob(pattern):
condense_xml(xml_file)
# Create final Office file as zip archive
output_file.parent.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(output_file, "w", zipfile.ZIP_DEFLATED) as zf:
for f in temp_content_dir.rglob("*"):
if f.is_file():
zf.write(f, f.relative_to(temp_content_dir))
# Validate if requested
if validate:
if not validate_document(output_file):
output_file.unlink() # Delete the corrupt file
return False
return True
def validate_document(doc_path):
"""Validate document by converting to HTML with soffice."""
# Determine the correct filter based on file extension
match doc_path.suffix.lower():
case ".docx":
filter_name = "html:HTML"
case ".pptx":
filter_name = "html:impress_html_Export"
case ".xlsx":
filter_name = "html:HTML (StarCalc)"
with tempfile.TemporaryDirectory() as temp_dir:
try:
result = subprocess.run(
[
"soffice",
"--headless",
"--convert-to",
filter_name,
"--outdir",
temp_dir,
str(doc_path),
],
capture_output=True,
timeout=10,
text=True,
)
if not (Path(temp_dir) / f"{doc_path.stem}.html").exists():
error_msg = result.stderr.strip() or "Document validation failed"
print(f"Validation error: {error_msg}", file=sys.stderr)
return False
return True
except FileNotFoundError:
print("Warning: soffice not found. Skipping validation.", file=sys.stderr)
return True
except subprocess.TimeoutExpired:
print("Validation error: Timeout during conversion", file=sys.stderr)
return False
except Exception as e:
print(f"Validation error: {e}", file=sys.stderr)
return False
def condense_xml(xml_file):
"""Strip unnecessary whitespace and remove comments."""
with open(xml_file, "r", encoding="utf-8") as f:
dom = defusedxml.minidom.parse(f)
# Process each element to remove whitespace and comments
for element in dom.getElementsByTagName("*"):
# Skip w:t elements and their processing
if element.tagName.endswith(":t"):
continue
# Remove whitespace-only text nodes and comment nodes
for child in list(element.childNodes):
if (
child.nodeType == child.TEXT_NODE
and child.nodeValue
and child.nodeValue.strip() == ""
) or child.nodeType == child.COMMENT_NODE:
element.removeChild(child)
# Write back the condensed XML
with open(xml_file, "wb") as f:
f.write(dom.toxml(encoding="UTF-8"))
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env python3
"""Unpack and format XML contents of Office files (.docx, .pptx, .xlsx)"""
import argparse
import random
import zipfile
import defusedxml.minidom
from pathlib import Path
def main():
parser = argparse.ArgumentParser(description="Unpack an Office file into a directory")
parser.add_argument("office_file", help="Office file (.docx/.pptx/.xlsx)")
parser.add_argument("output_dir", help="Output directory")
args = parser.parse_args()
unpack_document(args.office_file, args.output_dir)
def unpack_document(input_file, output_dir):
"""Unpack an Office file into a directory and pretty-print all XML files."""
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(input_file) as zf:
zf.extractall(output_path)
for pattern in ["*.xml", "*.rels"]:
for xml_file in output_path.rglob(pattern):
pretty_print_xml(xml_file)
# For .docx files, suggest an RSID for tracked changes
if str(input_file).endswith(".docx"):
suggested_rsid = "".join(random.choices("0123456789ABCDEF", k=8))
print(f"Suggested RSID for edit session: {suggested_rsid}")
def pretty_print_xml(xml_file):
"""Pretty-print a single XML file in place."""
content = xml_file.read_text(encoding="utf-8")
dom = defusedxml.minidom.parseString(content)
xml_file.write_bytes(dom.toprettyxml(indent=" ", encoding="ascii"))
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,70 @@
#!/usr/bin/env python3
"""
Command line tool to validate Office document XML files against XSD schemas and tracked changes.
Usage:
python validate.py <dir> --original <original_file>
"""
import argparse
import sys
from pathlib import Path
from validation import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator
def main():
parser = argparse.ArgumentParser(description="Validate Office document XML files")
parser.add_argument(
"unpacked_dir",
help="Path to unpacked Office document directory",
)
parser.add_argument(
"--original",
required=True,
help="Path to original file (.docx/.pptx/.xlsx)",
)
parser.add_argument(
"-v",
"--verbose",
action="store_true",
help="Enable verbose output",
)
args = parser.parse_args()
# Validate paths
unpacked_dir = Path(args.unpacked_dir)
original_file = Path(args.original)
file_extension = original_file.suffix.lower()
if not unpacked_dir.is_dir():
sys.exit(f"Error: {unpacked_dir} is not a directory")
if not original_file.is_file():
sys.exit(f"Error: {original_file} is not a file")
if file_extension not in [".docx", ".pptx", ".xlsx"]:
sys.exit(f"Error: {original_file} must be a .docx, .pptx, or .xlsx file")
# Run validations
match file_extension:
case ".docx":
validators = [DOCXSchemaValidator, RedliningValidator]
case ".pptx":
validators = [PPTXSchemaValidator]
case _:
print(f"Error: Validation not supported for file type {file_extension}")
sys.exit(1)
# Run validators
success = True
for V in validators:
validator = V(unpacked_dir, original_file, verbose=args.verbose)
if not validator.validate():
success = False
if success:
print("All validations PASSED!")
sys.exit(0 if success else 1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,15 @@
"""
Validation modules for Word document processing.
"""
from .base import BaseSchemaValidator
from .docx import DOCXSchemaValidator
from .pptx import PPTXSchemaValidator
from .redlining import RedliningValidator
__all__ = [
"BaseSchemaValidator",
"DOCXSchemaValidator",
"PPTXSchemaValidator",
"RedliningValidator",
]

View File

@@ -0,0 +1,948 @@
"""
Base validator with common validation logic for document files.
"""
import re
import tempfile
import zipfile
from pathlib import Path
import lxml.etree
class BaseSchemaValidator:
"""Base validator with common validation logic for document files."""
# Elements whose 'id' attributes must be unique within their file
# Format: element_name -> (attribute_name, scope)
# scope can be 'file' (unique within file) or 'global' (unique across all files)
UNIQUE_ID_REQUIREMENTS = {
# Word elements
"comment": ("id", "file"), # Comment IDs in comments.xml
"commentrangestart": ("id", "file"), # Must match comment IDs
"commentrangeend": ("id", "file"), # Must match comment IDs
"bookmarkstart": ("id", "file"), # Bookmark start IDs
"bookmarkend": ("id", "file"), # Bookmark end IDs
# Note: ins and del (track changes) can share IDs when part of same revision
# PowerPoint elements
"sldid": ("id", "file"), # Slide IDs in presentation.xml
"sldmasterid": ("id", "global"), # Slide master IDs must be globally unique
"sldlayoutid": ("id", "global"), # Slide layout IDs must be globally unique
"cm": ("authorid", "file"), # Comment author IDs
# Excel elements
"sheet": ("sheetid", "file"), # Sheet IDs in workbook.xml
"definedname": ("id", "file"), # Named range IDs
# Drawing/Shape elements (all formats)
"cxnsp": ("id", "file"), # Connection shape IDs
"sp": ("id", "file"), # Shape IDs
"pic": ("id", "file"), # Picture IDs
"grpsp": ("id", "file"), # Group shape IDs
}
# Mapping of element names to expected relationship types
# Subclasses should override this with format-specific mappings
ELEMENT_RELATIONSHIP_TYPES = {}
# Unified schema mappings for all Office document types
SCHEMA_MAPPINGS = {
# Document type specific schemas
"word": "ISO-IEC29500-4_2016/wml.xsd", # Word documents
"ppt": "ISO-IEC29500-4_2016/pml.xsd", # PowerPoint presentations
"xl": "ISO-IEC29500-4_2016/sml.xsd", # Excel spreadsheets
# Common file types
"[Content_Types].xml": "ecma/fouth-edition/opc-contentTypes.xsd",
"app.xml": "ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd",
"core.xml": "ecma/fouth-edition/opc-coreProperties.xsd",
"custom.xml": "ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd",
".rels": "ecma/fouth-edition/opc-relationships.xsd",
# Word-specific files
"people.xml": "microsoft/wml-2012.xsd",
"commentsIds.xml": "microsoft/wml-cid-2016.xsd",
"commentsExtensible.xml": "microsoft/wml-cex-2018.xsd",
"commentsExtended.xml": "microsoft/wml-2012.xsd",
# Chart files (common across document types)
"chart": "ISO-IEC29500-4_2016/dml-chart.xsd",
# Theme files (common across document types)
"theme": "ISO-IEC29500-4_2016/dml-main.xsd",
# Drawing and media files
"drawing": "ISO-IEC29500-4_2016/dml-main.xsd",
}
# Unified namespace constants
MC_NAMESPACE = "http://schemas.openxmlformats.org/markup-compatibility/2006"
XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace"
# Common OOXML namespaces used across validators
PACKAGE_RELATIONSHIPS_NAMESPACE = (
"http://schemas.openxmlformats.org/package/2006/relationships"
)
OFFICE_RELATIONSHIPS_NAMESPACE = (
"http://schemas.openxmlformats.org/officeDocument/2006/relationships"
)
CONTENT_TYPES_NAMESPACE = (
"http://schemas.openxmlformats.org/package/2006/content-types"
)
# Folders where we should clean ignorable namespaces
MAIN_CONTENT_FOLDERS = {"word", "ppt", "xl"}
# All allowed OOXML namespaces (superset of all document types)
OOXML_NAMESPACES = {
"http://schemas.openxmlformats.org/officeDocument/2006/math",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships",
"http://schemas.openxmlformats.org/schemaLibrary/2006/main",
"http://schemas.openxmlformats.org/drawingml/2006/main",
"http://schemas.openxmlformats.org/drawingml/2006/chart",
"http://schemas.openxmlformats.org/drawingml/2006/chartDrawing",
"http://schemas.openxmlformats.org/drawingml/2006/diagram",
"http://schemas.openxmlformats.org/drawingml/2006/picture",
"http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing",
"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing",
"http://schemas.openxmlformats.org/wordprocessingml/2006/main",
"http://schemas.openxmlformats.org/presentationml/2006/main",
"http://schemas.openxmlformats.org/spreadsheetml/2006/main",
"http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes",
"http://www.w3.org/XML/1998/namespace",
}
def __init__(self, unpacked_dir, original_file, verbose=False):
self.unpacked_dir = Path(unpacked_dir).resolve()
self.original_file = Path(original_file)
self.verbose = verbose
# Set schemas directory
self.schemas_dir = Path(__file__).parent.parent.parent / "schemas"
# Get all XML and .rels files
patterns = ["*.xml", "*.rels"]
self.xml_files = [
f for pattern in patterns for f in self.unpacked_dir.rglob(pattern)
]
if not self.xml_files:
print(f"Warning: No XML files found in {self.unpacked_dir}")
def validate(self):
"""Run all validation checks and return True if all pass."""
raise NotImplementedError("Subclasses must implement the validate method")
def validate_xml(self):
"""Validate that all XML files are well-formed."""
errors = []
for xml_file in self.xml_files:
try:
# Try to parse the XML file
lxml.etree.parse(str(xml_file))
except lxml.etree.XMLSyntaxError as e:
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: "
f"Line {e.lineno}: {e.msg}"
)
except Exception as e:
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: "
f"Unexpected error: {str(e)}"
)
if errors:
print(f"FAILED - Found {len(errors)} XML violations:")
for error in errors:
print(error)
return False
else:
if self.verbose:
print("PASSED - All XML files are well-formed")
return True
def validate_namespaces(self):
"""Validate that namespace prefixes in Ignorable attributes are declared."""
errors = []
for xml_file in self.xml_files:
try:
root = lxml.etree.parse(str(xml_file)).getroot()
declared = set(root.nsmap.keys()) - {None} # Exclude default namespace
for attr_val in [
v for k, v in root.attrib.items() if k.endswith("Ignorable")
]:
undeclared = set(attr_val.split()) - declared
errors.extend(
f" {xml_file.relative_to(self.unpacked_dir)}: "
f"Namespace '{ns}' in Ignorable but not declared"
for ns in undeclared
)
except lxml.etree.XMLSyntaxError:
continue
if errors:
print(f"FAILED - {len(errors)} namespace issues:")
for error in errors:
print(error)
return False
if self.verbose:
print("PASSED - All namespace prefixes properly declared")
return True
def validate_unique_ids(self):
"""Validate that specific IDs are unique according to OOXML requirements."""
errors = []
global_ids = {} # Track globally unique IDs across all files
for xml_file in self.xml_files:
try:
root = lxml.etree.parse(str(xml_file)).getroot()
file_ids = {} # Track IDs that must be unique within this file
# Remove all mc:AlternateContent elements from the tree
mc_elements = root.xpath(
".//mc:AlternateContent", namespaces={"mc": self.MC_NAMESPACE}
)
for elem in mc_elements:
elem.getparent().remove(elem)
# Now check IDs in the cleaned tree
for elem in root.iter():
# Get the element name without namespace
tag = (
elem.tag.split("}")[-1].lower()
if "}" in elem.tag
else elem.tag.lower()
)
# Check if this element type has ID uniqueness requirements
if tag in self.UNIQUE_ID_REQUIREMENTS:
attr_name, scope = self.UNIQUE_ID_REQUIREMENTS[tag]
# Look for the specified attribute
id_value = None
for attr, value in elem.attrib.items():
attr_local = (
attr.split("}")[-1].lower()
if "}" in attr
else attr.lower()
)
if attr_local == attr_name:
id_value = value
break
if id_value is not None:
if scope == "global":
# Check global uniqueness
if id_value in global_ids:
prev_file, prev_line, prev_tag = global_ids[
id_value
]
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: "
f"Line {elem.sourceline}: Global ID '{id_value}' in <{tag}> "
f"already used in {prev_file} at line {prev_line} in <{prev_tag}>"
)
else:
global_ids[id_value] = (
xml_file.relative_to(self.unpacked_dir),
elem.sourceline,
tag,
)
elif scope == "file":
# Check file-level uniqueness
key = (tag, attr_name)
if key not in file_ids:
file_ids[key] = {}
if id_value in file_ids[key]:
prev_line = file_ids[key][id_value]
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: "
f"Line {elem.sourceline}: Duplicate {attr_name}='{id_value}' in <{tag}> "
f"(first occurrence at line {prev_line})"
)
else:
file_ids[key][id_value] = elem.sourceline
except (lxml.etree.XMLSyntaxError, Exception) as e:
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}"
)
if errors:
print(f"FAILED - Found {len(errors)} ID uniqueness violations:")
for error in errors:
print(error)
return False
else:
if self.verbose:
print("PASSED - All required IDs are unique")
return True
def validate_file_references(self):
"""
Validate that all .rels files properly reference files and that all files are referenced.
"""
errors = []
# Find all .rels files
rels_files = list(self.unpacked_dir.rglob("*.rels"))
if not rels_files:
if self.verbose:
print("PASSED - No .rels files found")
return True
# Get all files in the unpacked directory (excluding reference files)
all_files = []
for file_path in self.unpacked_dir.rglob("*"):
if (
file_path.is_file()
and file_path.name != "[Content_Types].xml"
and not file_path.name.endswith(".rels")
): # This file is not referenced by .rels
all_files.append(file_path.resolve())
# Track all files that are referenced by any .rels file
all_referenced_files = set()
if self.verbose:
print(
f"Found {len(rels_files)} .rels files and {len(all_files)} target files"
)
# Check each .rels file
for rels_file in rels_files:
try:
# Parse relationships file
rels_root = lxml.etree.parse(str(rels_file)).getroot()
# Get the directory where this .rels file is located
rels_dir = rels_file.parent
# Find all relationships and their targets
referenced_files = set()
broken_refs = []
for rel in rels_root.findall(
".//ns:Relationship",
namespaces={"ns": self.PACKAGE_RELATIONSHIPS_NAMESPACE},
):
target = rel.get("Target")
if target and not target.startswith(
("http", "mailto:")
): # Skip external URLs
# Resolve the target path relative to the .rels file location
if rels_file.name == ".rels":
# Root .rels file - targets are relative to unpacked_dir
target_path = self.unpacked_dir / target
else:
# Other .rels files - targets are relative to their parent's parent
# e.g., word/_rels/document.xml.rels -> targets relative to word/
base_dir = rels_dir.parent
target_path = base_dir / target
# Normalize the path and check if it exists
try:
target_path = target_path.resolve()
if target_path.exists() and target_path.is_file():
referenced_files.add(target_path)
all_referenced_files.add(target_path)
else:
broken_refs.append((target, rel.sourceline))
except (OSError, ValueError):
broken_refs.append((target, rel.sourceline))
# Report broken references
if broken_refs:
rel_path = rels_file.relative_to(self.unpacked_dir)
for broken_ref, line_num in broken_refs:
errors.append(
f" {rel_path}: Line {line_num}: Broken reference to {broken_ref}"
)
except Exception as e:
rel_path = rels_file.relative_to(self.unpacked_dir)
errors.append(f" Error parsing {rel_path}: {e}")
# Check for unreferenced files (files that exist but are not referenced anywhere)
unreferenced_files = set(all_files) - all_referenced_files
if unreferenced_files:
for unref_file in sorted(unreferenced_files):
unref_rel_path = unref_file.relative_to(self.unpacked_dir)
errors.append(f" Unreferenced file: {unref_rel_path}")
if errors:
print(f"FAILED - Found {len(errors)} relationship validation errors:")
for error in errors:
print(error)
print(
"CRITICAL: These errors will cause the document to appear corrupt. "
+ "Broken references MUST be fixed, "
+ "and unreferenced files MUST be referenced or removed."
)
return False
else:
if self.verbose:
print(
"PASSED - All references are valid and all files are properly referenced"
)
return True
def validate_all_relationship_ids(self):
"""
Validate that all r:id attributes in XML files reference existing IDs
in their corresponding .rels files, and optionally validate relationship types.
"""
errors = []
# Process each XML file that might contain r:id references
for xml_file in self.xml_files:
# Skip .rels files themselves
if xml_file.suffix == ".rels":
continue
# Determine the corresponding .rels file
# For dir/file.xml, it's dir/_rels/file.xml.rels
rels_dir = xml_file.parent / "_rels"
rels_file = rels_dir / f"{xml_file.name}.rels"
# Skip if there's no corresponding .rels file (that's okay)
if not rels_file.exists():
continue
try:
# Parse the .rels file to get valid relationship IDs and their types
rels_root = lxml.etree.parse(str(rels_file)).getroot()
rid_to_type = {}
for rel in rels_root.findall(
f".//{{{self.PACKAGE_RELATIONSHIPS_NAMESPACE}}}Relationship"
):
rid = rel.get("Id")
rel_type = rel.get("Type", "")
if rid:
# Check for duplicate rIds
if rid in rid_to_type:
rels_rel_path = rels_file.relative_to(self.unpacked_dir)
errors.append(
f" {rels_rel_path}: Line {rel.sourceline}: "
f"Duplicate relationship ID '{rid}' (IDs must be unique)"
)
# Extract just the type name from the full URL
type_name = (
rel_type.split("/")[-1] if "/" in rel_type else rel_type
)
rid_to_type[rid] = type_name
# Parse the XML file to find all r:id references
xml_root = lxml.etree.parse(str(xml_file)).getroot()
# Find all elements with r:id attributes
for elem in xml_root.iter():
# Check for r:id attribute (relationship ID)
rid_attr = elem.get(f"{{{self.OFFICE_RELATIONSHIPS_NAMESPACE}}}id")
if rid_attr:
xml_rel_path = xml_file.relative_to(self.unpacked_dir)
elem_name = (
elem.tag.split("}")[-1] if "}" in elem.tag else elem.tag
)
# Check if the ID exists
if rid_attr not in rid_to_type:
errors.append(
f" {xml_rel_path}: Line {elem.sourceline}: "
f"<{elem_name}> references non-existent relationship '{rid_attr}' "
f"(valid IDs: {', '.join(sorted(rid_to_type.keys())[:5])}{'...' if len(rid_to_type) > 5 else ''})"
)
# Check if we have type expectations for this element
elif self.ELEMENT_RELATIONSHIP_TYPES:
expected_type = self._get_expected_relationship_type(
elem_name
)
if expected_type:
actual_type = rid_to_type[rid_attr]
# Check if the actual type matches or contains the expected type
if expected_type not in actual_type.lower():
errors.append(
f" {xml_rel_path}: Line {elem.sourceline}: "
f"<{elem_name}> references '{rid_attr}' which points to '{actual_type}' "
f"but should point to a '{expected_type}' relationship"
)
except Exception as e:
xml_rel_path = xml_file.relative_to(self.unpacked_dir)
errors.append(f" Error processing {xml_rel_path}: {e}")
if errors:
print(f"FAILED - Found {len(errors)} relationship ID reference errors:")
for error in errors:
print(error)
print("\nThese ID mismatches will cause the document to appear corrupt!")
return False
else:
if self.verbose:
print("PASSED - All relationship ID references are valid")
return True
def _get_expected_relationship_type(self, element_name):
"""
Get the expected relationship type for an element.
First checks the explicit mapping, then tries pattern detection.
"""
# Normalize element name to lowercase
elem_lower = element_name.lower()
# Check explicit mapping first
if elem_lower in self.ELEMENT_RELATIONSHIP_TYPES:
return self.ELEMENT_RELATIONSHIP_TYPES[elem_lower]
# Try pattern detection for common patterns
# Pattern 1: Elements ending in "Id" often expect a relationship of the prefix type
if elem_lower.endswith("id") and len(elem_lower) > 2:
# e.g., "sldId" -> "sld", "sldMasterId" -> "sldMaster"
prefix = elem_lower[:-2] # Remove "id"
# Check if this might be a compound like "sldMasterId"
if prefix.endswith("master"):
return prefix.lower()
elif prefix.endswith("layout"):
return prefix.lower()
else:
# Simple case like "sldId" -> "slide"
# Common transformations
if prefix == "sld":
return "slide"
return prefix.lower()
# Pattern 2: Elements ending in "Reference" expect a relationship of the prefix type
if elem_lower.endswith("reference") and len(elem_lower) > 9:
prefix = elem_lower[:-9] # Remove "reference"
return prefix.lower()
return None
def validate_content_types(self):
"""Validate that all content files are properly declared in [Content_Types].xml."""
errors = []
# Find [Content_Types].xml file
content_types_file = self.unpacked_dir / "[Content_Types].xml"
if not content_types_file.exists():
print("FAILED - [Content_Types].xml file not found")
return False
try:
# Parse and get all declared parts and extensions
root = lxml.etree.parse(str(content_types_file)).getroot()
declared_parts = set()
declared_extensions = set()
# Get Override declarations (specific files)
for override in root.findall(
f".//{{{self.CONTENT_TYPES_NAMESPACE}}}Override"
):
part_name = override.get("PartName")
if part_name is not None:
declared_parts.add(part_name.lstrip("/"))
# Get Default declarations (by extension)
for default in root.findall(
f".//{{{self.CONTENT_TYPES_NAMESPACE}}}Default"
):
extension = default.get("Extension")
if extension is not None:
declared_extensions.add(extension.lower())
# Root elements that require content type declaration
declarable_roots = {
"sld",
"sldLayout",
"sldMaster",
"presentation", # PowerPoint
"document", # Word
"workbook",
"worksheet", # Excel
"theme", # Common
}
# Common media file extensions that should be declared
media_extensions = {
"png": "image/png",
"jpg": "image/jpeg",
"jpeg": "image/jpeg",
"gif": "image/gif",
"bmp": "image/bmp",
"tiff": "image/tiff",
"wmf": "image/x-wmf",
"emf": "image/x-emf",
}
# Get all files in the unpacked directory
all_files = list(self.unpacked_dir.rglob("*"))
all_files = [f for f in all_files if f.is_file()]
# Check all XML files for Override declarations
for xml_file in self.xml_files:
path_str = str(xml_file.relative_to(self.unpacked_dir)).replace(
"\\", "/"
)
# Skip non-content files
if any(
skip in path_str
for skip in [".rels", "[Content_Types]", "docProps/", "_rels/"]
):
continue
try:
root_tag = lxml.etree.parse(str(xml_file)).getroot().tag
root_name = root_tag.split("}")[-1] if "}" in root_tag else root_tag
if root_name in declarable_roots and path_str not in declared_parts:
errors.append(
f" {path_str}: File with <{root_name}> root not declared in [Content_Types].xml"
)
except Exception:
continue # Skip unparseable files
# Check all non-XML files for Default extension declarations
for file_path in all_files:
# Skip XML files and metadata files (already checked above)
if file_path.suffix.lower() in {".xml", ".rels"}:
continue
if file_path.name == "[Content_Types].xml":
continue
if "_rels" in file_path.parts or "docProps" in file_path.parts:
continue
extension = file_path.suffix.lstrip(".").lower()
if extension and extension not in declared_extensions:
# Check if it's a known media extension that should be declared
if extension in media_extensions:
relative_path = file_path.relative_to(self.unpacked_dir)
errors.append(
f' {relative_path}: File with extension \'{extension}\' not declared in [Content_Types].xml - should add: <Default Extension="{extension}" ContentType="{media_extensions[extension]}"/>'
)
except Exception as e:
errors.append(f" Error parsing [Content_Types].xml: {e}")
if errors:
print(f"FAILED - Found {len(errors)} content type declaration errors:")
for error in errors:
print(error)
return False
else:
if self.verbose:
print(
"PASSED - All content files are properly declared in [Content_Types].xml"
)
return True
def validate_file_against_xsd(self, xml_file, verbose=False):
"""Validate a single XML file against XSD schema, comparing with original.
Args:
xml_file: Path to XML file to validate
verbose: Enable verbose output
Returns:
tuple: (is_valid, new_errors_set) where is_valid is True/False/None (skipped)
"""
# Resolve both paths to handle symlinks
xml_file = Path(xml_file).resolve()
unpacked_dir = self.unpacked_dir.resolve()
# Validate current file
is_valid, current_errors = self._validate_single_file_xsd(
xml_file, unpacked_dir
)
if is_valid is None:
return None, set() # Skipped
elif is_valid:
return True, set() # Valid, no errors
# Get errors from original file for this specific file
original_errors = self._get_original_file_errors(xml_file)
# Compare with original (both are guaranteed to be sets here)
assert current_errors is not None
new_errors = current_errors - original_errors
if new_errors:
if verbose:
relative_path = xml_file.relative_to(unpacked_dir)
print(f"FAILED - {relative_path}: {len(new_errors)} new error(s)")
for error in list(new_errors)[:3]:
truncated = error[:250] + "..." if len(error) > 250 else error
print(f" - {truncated}")
return False, new_errors
else:
# All errors existed in original
if verbose:
print(
f"PASSED - No new errors (original had {len(current_errors)} errors)"
)
return True, set()
def validate_against_xsd(self):
"""Validate XML files against XSD schemas, showing only new errors compared to original."""
new_errors = []
original_error_count = 0
valid_count = 0
skipped_count = 0
for xml_file in self.xml_files:
relative_path = str(xml_file.relative_to(self.unpacked_dir))
is_valid, new_file_errors = self.validate_file_against_xsd(
xml_file, verbose=False
)
if is_valid is None:
skipped_count += 1
continue
elif is_valid and not new_file_errors:
valid_count += 1
continue
elif is_valid:
# Had errors but all existed in original
original_error_count += 1
valid_count += 1
continue
# Has new errors
new_errors.append(f" {relative_path}: {len(new_file_errors)} new error(s)")
for error in list(new_file_errors)[:3]: # Show first 3 errors
new_errors.append(
f" - {error[:250]}..." if len(error) > 250 else f" - {error}"
)
# Print summary
if self.verbose:
print(f"Validated {len(self.xml_files)} files:")
print(f" - Valid: {valid_count}")
print(f" - Skipped (no schema): {skipped_count}")
if original_error_count:
print(f" - With original errors (ignored): {original_error_count}")
print(
f" - With NEW errors: {len(new_errors) > 0 and len([e for e in new_errors if not e.startswith(' ')]) or 0}"
)
if new_errors:
print("\nFAILED - Found NEW validation errors:")
for error in new_errors:
print(error)
return False
else:
if self.verbose:
print("\nPASSED - No new XSD validation errors introduced")
return True
def _get_schema_path(self, xml_file):
"""Determine the appropriate schema path for an XML file."""
# Check exact filename match
if xml_file.name in self.SCHEMA_MAPPINGS:
return self.schemas_dir / self.SCHEMA_MAPPINGS[xml_file.name]
# Check .rels files
if xml_file.suffix == ".rels":
return self.schemas_dir / self.SCHEMA_MAPPINGS[".rels"]
# Check chart files
if "charts/" in str(xml_file) and xml_file.name.startswith("chart"):
return self.schemas_dir / self.SCHEMA_MAPPINGS["chart"]
# Check theme files
if "theme/" in str(xml_file) and xml_file.name.startswith("theme"):
return self.schemas_dir / self.SCHEMA_MAPPINGS["theme"]
# Check if file is in a main content folder and use appropriate schema
if xml_file.parent.name in self.MAIN_CONTENT_FOLDERS:
return self.schemas_dir / self.SCHEMA_MAPPINGS[xml_file.parent.name]
return None
def _clean_ignorable_namespaces(self, xml_doc):
"""Remove attributes and elements not in allowed namespaces."""
# Create a clean copy
xml_string = lxml.etree.tostring(xml_doc, encoding="unicode")
xml_copy = lxml.etree.fromstring(xml_string)
# Remove attributes not in allowed namespaces
for elem in xml_copy.iter():
attrs_to_remove = []
for attr in elem.attrib:
# Check if attribute is from a namespace other than allowed ones
if "{" in attr:
ns = attr.split("}")[0][1:]
if ns not in self.OOXML_NAMESPACES:
attrs_to_remove.append(attr)
# Remove collected attributes
for attr in attrs_to_remove:
del elem.attrib[attr]
# Remove elements not in allowed namespaces
self._remove_ignorable_elements(xml_copy)
return lxml.etree.ElementTree(xml_copy)
def _remove_ignorable_elements(self, root):
"""Recursively remove all elements not in allowed namespaces."""
elements_to_remove = []
# Find elements to remove
for elem in list(root):
# Skip non-element nodes (comments, processing instructions, etc.)
if not hasattr(elem, "tag") or callable(elem.tag):
continue
tag_str = str(elem.tag)
if tag_str.startswith("{"):
ns = tag_str.split("}")[0][1:]
if ns not in self.OOXML_NAMESPACES:
elements_to_remove.append(elem)
continue
# Recursively clean child elements
self._remove_ignorable_elements(elem)
# Remove collected elements
for elem in elements_to_remove:
root.remove(elem)
def _preprocess_for_mc_ignorable(self, xml_doc):
"""Preprocess XML to handle mc:Ignorable attribute properly."""
# Remove mc:Ignorable attributes before validation
root = xml_doc.getroot()
# Remove mc:Ignorable attribute from root
if f"{{{self.MC_NAMESPACE}}}Ignorable" in root.attrib:
del root.attrib[f"{{{self.MC_NAMESPACE}}}Ignorable"]
return xml_doc
def _validate_single_file_xsd(self, xml_file, base_path):
"""Validate a single XML file against XSD schema. Returns (is_valid, errors_set)."""
schema_path = self._get_schema_path(xml_file)
if not schema_path:
return None, None # Skip file
try:
# Load schema
with open(schema_path, "rb") as xsd_file:
parser = lxml.etree.XMLParser()
xsd_doc = lxml.etree.parse(
xsd_file, parser=parser, base_url=str(schema_path)
)
schema = lxml.etree.XMLSchema(xsd_doc)
# Load and preprocess XML
with open(xml_file, "r") as f:
xml_doc = lxml.etree.parse(f)
xml_doc, _ = self._remove_template_tags_from_text_nodes(xml_doc)
xml_doc = self._preprocess_for_mc_ignorable(xml_doc)
# Clean ignorable namespaces if needed
relative_path = xml_file.relative_to(base_path)
if (
relative_path.parts
and relative_path.parts[0] in self.MAIN_CONTENT_FOLDERS
):
xml_doc = self._clean_ignorable_namespaces(xml_doc)
# Validate
if schema.validate(xml_doc):
return True, set()
else:
errors = set()
for error in schema.error_log:
# Store normalized error message (without line numbers for comparison)
errors.add(error.message)
return False, errors
except Exception as e:
return False, {str(e)}
def _get_original_file_errors(self, xml_file):
"""Get XSD validation errors from a single file in the original document.
Args:
xml_file: Path to the XML file in unpacked_dir to check
Returns:
set: Set of error messages from the original file
"""
# Resolve both paths to handle symlinks (e.g., /var vs /private/var on macOS)
xml_file = Path(xml_file).resolve()
unpacked_dir = self.unpacked_dir.resolve()
relative_path = xml_file.relative_to(unpacked_dir)
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
# Extract original file
with zipfile.ZipFile(self.original_file, "r") as zip_ref:
zip_ref.extractall(temp_path)
# Find corresponding file in original
original_xml_file = temp_path / relative_path
if not original_xml_file.exists():
# File didn't exist in original, so no original errors
return set()
# Validate the specific file in original
is_valid, errors = self._validate_single_file_xsd(
original_xml_file, temp_path
)
return errors if errors else set()
def _remove_template_tags_from_text_nodes(self, xml_doc):
"""Remove template tags from XML text nodes and collect warnings.
Template tags follow the pattern {{ ... }} and are used as placeholders
for content replacement. They should be removed from text content before
XSD validation while preserving XML structure.
Returns:
tuple: (cleaned_xml_doc, warnings_list)
"""
warnings = []
template_pattern = re.compile(r"\{\{[^}]*\}\}")
# Create a copy of the document to avoid modifying the original
xml_string = lxml.etree.tostring(xml_doc, encoding="unicode")
xml_copy = lxml.etree.fromstring(xml_string)
def process_text_content(text, content_type):
if not text:
return text
matches = list(template_pattern.finditer(text))
if matches:
for match in matches:
warnings.append(
f"Found template tag in {content_type}: {match.group()}"
)
return template_pattern.sub("", text)
return text
# Process all text nodes in the document
for elem in xml_copy.iter():
# Skip processing if this is a w:t element
if not hasattr(elem, "tag") or callable(elem.tag):
continue
tag_str = str(elem.tag)
if tag_str.endswith("}t") or tag_str == "t":
continue
elem.text = process_text_content(elem.text, "text content")
elem.tail = process_text_content(elem.tail, "tail content")
return lxml.etree.ElementTree(xml_copy), warnings
if __name__ == "__main__":
raise RuntimeError("This module should not be run directly.")

View File

@@ -0,0 +1,274 @@
"""
Validator for Word document XML files against XSD schemas.
"""
import re
import tempfile
import zipfile
import lxml.etree
from .base import BaseSchemaValidator
class DOCXSchemaValidator(BaseSchemaValidator):
"""Validator for Word document XML files against XSD schemas."""
# Word-specific namespace
WORD_2006_NAMESPACE = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
# Word-specific element to relationship type mappings
# Start with empty mapping - add specific cases as we discover them
ELEMENT_RELATIONSHIP_TYPES = {}
def validate(self):
"""Run all validation checks and return True if all pass."""
# Test 0: XML well-formedness
if not self.validate_xml():
return False
# Test 1: Namespace declarations
all_valid = True
if not self.validate_namespaces():
all_valid = False
# Test 2: Unique IDs
if not self.validate_unique_ids():
all_valid = False
# Test 3: Relationship and file reference validation
if not self.validate_file_references():
all_valid = False
# Test 4: Content type declarations
if not self.validate_content_types():
all_valid = False
# Test 5: XSD schema validation
if not self.validate_against_xsd():
all_valid = False
# Test 6: Whitespace preservation
if not self.validate_whitespace_preservation():
all_valid = False
# Test 7: Deletion validation
if not self.validate_deletions():
all_valid = False
# Test 8: Insertion validation
if not self.validate_insertions():
all_valid = False
# Test 9: Relationship ID reference validation
if not self.validate_all_relationship_ids():
all_valid = False
# Count and compare paragraphs
self.compare_paragraph_counts()
return all_valid
def validate_whitespace_preservation(self):
"""
Validate that w:t elements with whitespace have xml:space='preserve'.
"""
errors = []
for xml_file in self.xml_files:
# Only check document.xml files
if xml_file.name != "document.xml":
continue
try:
root = lxml.etree.parse(str(xml_file)).getroot()
# Find all w:t elements
for elem in root.iter(f"{{{self.WORD_2006_NAMESPACE}}}t"):
if elem.text:
text = elem.text
# Check if text starts or ends with whitespace
if re.match(r"^\s.*", text) or re.match(r".*\s$", text):
# Check if xml:space="preserve" attribute exists
xml_space_attr = f"{{{self.XML_NAMESPACE}}}space"
if (
xml_space_attr not in elem.attrib
or elem.attrib[xml_space_attr] != "preserve"
):
# Show a preview of the text
text_preview = (
repr(text)[:50] + "..."
if len(repr(text)) > 50
else repr(text)
)
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: "
f"Line {elem.sourceline}: w:t element with whitespace missing xml:space='preserve': {text_preview}"
)
except (lxml.etree.XMLSyntaxError, Exception) as e:
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}"
)
if errors:
print(f"FAILED - Found {len(errors)} whitespace preservation violations:")
for error in errors:
print(error)
return False
else:
if self.verbose:
print("PASSED - All whitespace is properly preserved")
return True
def validate_deletions(self):
"""
Validate that w:t elements are not within w:del elements.
For some reason, XSD validation does not catch this, so we do it manually.
"""
errors = []
for xml_file in self.xml_files:
# Only check document.xml files
if xml_file.name != "document.xml":
continue
try:
root = lxml.etree.parse(str(xml_file)).getroot()
# Find all w:t elements that are descendants of w:del elements
namespaces = {"w": self.WORD_2006_NAMESPACE}
xpath_expression = ".//w:del//w:t"
problematic_t_elements = root.xpath(
xpath_expression, namespaces=namespaces
)
for t_elem in problematic_t_elements:
if t_elem.text:
# Show a preview of the text
text_preview = (
repr(t_elem.text)[:50] + "..."
if len(repr(t_elem.text)) > 50
else repr(t_elem.text)
)
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: "
f"Line {t_elem.sourceline}: <w:t> found within <w:del>: {text_preview}"
)
except (lxml.etree.XMLSyntaxError, Exception) as e:
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}"
)
if errors:
print(f"FAILED - Found {len(errors)} deletion validation violations:")
for error in errors:
print(error)
return False
else:
if self.verbose:
print("PASSED - No w:t elements found within w:del elements")
return True
def count_paragraphs_in_unpacked(self):
"""Count the number of paragraphs in the unpacked document."""
count = 0
for xml_file in self.xml_files:
# Only check document.xml files
if xml_file.name != "document.xml":
continue
try:
root = lxml.etree.parse(str(xml_file)).getroot()
# Count all w:p elements
paragraphs = root.findall(f".//{{{self.WORD_2006_NAMESPACE}}}p")
count = len(paragraphs)
except Exception as e:
print(f"Error counting paragraphs in unpacked document: {e}")
return count
def count_paragraphs_in_original(self):
"""Count the number of paragraphs in the original docx file."""
count = 0
try:
# Create temporary directory to unpack original
with tempfile.TemporaryDirectory() as temp_dir:
# Unpack original docx
with zipfile.ZipFile(self.original_file, "r") as zip_ref:
zip_ref.extractall(temp_dir)
# Parse document.xml
doc_xml_path = temp_dir + "/word/document.xml"
root = lxml.etree.parse(doc_xml_path).getroot()
# Count all w:p elements
paragraphs = root.findall(f".//{{{self.WORD_2006_NAMESPACE}}}p")
count = len(paragraphs)
except Exception as e:
print(f"Error counting paragraphs in original document: {e}")
return count
def validate_insertions(self):
"""
Validate that w:delText elements are not within w:ins elements.
w:delText is only allowed in w:ins if nested within a w:del.
"""
errors = []
for xml_file in self.xml_files:
if xml_file.name != "document.xml":
continue
try:
root = lxml.etree.parse(str(xml_file)).getroot()
namespaces = {"w": self.WORD_2006_NAMESPACE}
# Find w:delText in w:ins that are NOT within w:del
invalid_elements = root.xpath(
".//w:ins//w:delText[not(ancestor::w:del)]",
namespaces=namespaces
)
for elem in invalid_elements:
text_preview = (
repr(elem.text or "")[:50] + "..."
if len(repr(elem.text or "")) > 50
else repr(elem.text or "")
)
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: "
f"Line {elem.sourceline}: <w:delText> within <w:ins>: {text_preview}"
)
except (lxml.etree.XMLSyntaxError, Exception) as e:
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}"
)
if errors:
print(f"FAILED - Found {len(errors)} insertion validation violations:")
for error in errors:
print(error)
return False
else:
if self.verbose:
print("PASSED - No w:delText elements within w:ins elements")
return True
def compare_paragraph_counts(self):
"""Compare paragraph counts between original and new document."""
original_count = self.count_paragraphs_in_original()
new_count = self.count_paragraphs_in_unpacked()
diff = new_count - original_count
diff_str = f"+{diff}" if diff > 0 else str(diff)
print(f"\nParagraphs: {original_count}{new_count} ({diff_str})")
if __name__ == "__main__":
raise RuntimeError("This module should not be run directly.")

View File

@@ -0,0 +1,309 @@
"""
Validator for PowerPoint presentation XML files against XSD schemas.
"""
import re
import lxml.etree
from .base import BaseSchemaValidator
class PPTXSchemaValidator(BaseSchemaValidator):
"""Validator for PowerPoint presentation XML files against XSD schemas."""
# PowerPoint presentation namespace
PRESENTATIONML_NAMESPACE = (
"http://schemas.openxmlformats.org/presentationml/2006/main"
)
# PowerPoint-specific element to relationship type mappings
ELEMENT_RELATIONSHIP_TYPES = {
"sldid": "slide",
"sldmasterid": "slidemaster",
"notesmasterid": "notesmaster",
"sldlayoutid": "slidelayout",
"themeid": "theme",
"tablestyleid": "tablestyles",
}
def validate(self):
"""Run all validation checks and return True if all pass."""
# Test 0: XML well-formedness
if not self.validate_xml():
return False
# Test 1: Namespace declarations
all_valid = True
if not self.validate_namespaces():
all_valid = False
# Test 2: Unique IDs
if not self.validate_unique_ids():
all_valid = False
# Test 3: UUID ID validation
if not self.validate_uuid_ids():
all_valid = False
# Test 4: Relationship and file reference validation
if not self.validate_file_references():
all_valid = False
# Test 5: Slide layout ID validation
if not self.validate_slide_layout_ids():
all_valid = False
# Test 6: Content type declarations
if not self.validate_content_types():
all_valid = False
# Test 7: XSD schema validation
if not self.validate_against_xsd():
all_valid = False
# Test 8: Notes slide reference validation
if not self.validate_notes_slide_references():
all_valid = False
# Test 9: Relationship ID reference validation
if not self.validate_all_relationship_ids():
all_valid = False
# Test 10: Duplicate slide layout references validation
if not self.validate_no_duplicate_slide_layouts():
all_valid = False
return all_valid
def validate_uuid_ids(self):
"""Validate that ID attributes that look like UUIDs contain only hex values."""
errors = []
# UUID pattern: 8-4-4-4-12 hex digits with optional braces/hyphens
uuid_pattern = re.compile(
r"^[\{\(]?[0-9A-Fa-f]{8}-?[0-9A-Fa-f]{4}-?[0-9A-Fa-f]{4}-?[0-9A-Fa-f]{4}-?[0-9A-Fa-f]{12}[\}\)]?$"
)
for xml_file in self.xml_files:
try:
root = lxml.etree.parse(str(xml_file)).getroot()
# Check all elements for ID attributes
for elem in root.iter():
for attr, value in elem.attrib.items():
# Check if this is an ID attribute
attr_name = attr.split("}")[-1].lower()
if attr_name == "id" or attr_name.endswith("id"):
# Check if value looks like a UUID (has the right length and pattern structure)
if self._looks_like_uuid(value):
# Validate that it contains only hex characters in the right positions
if not uuid_pattern.match(value):
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: "
f"Line {elem.sourceline}: ID '{value}' appears to be a UUID but contains invalid hex characters"
)
except (lxml.etree.XMLSyntaxError, Exception) as e:
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}"
)
if errors:
print(f"FAILED - Found {len(errors)} UUID ID validation errors:")
for error in errors:
print(error)
return False
else:
if self.verbose:
print("PASSED - All UUID-like IDs contain valid hex values")
return True
def _looks_like_uuid(self, value):
"""Check if a value has the general structure of a UUID."""
# Remove common UUID delimiters
clean_value = value.strip("{}()").replace("-", "")
# Check if it's 32 hex-like characters (could include invalid hex chars)
return len(clean_value) == 32 and all(c.isalnum() for c in clean_value)
def validate_slide_layout_ids(self):
"""Validate that sldLayoutId elements in slide masters reference valid slide layouts."""
errors = []
# Find all slide master files
slide_masters = list(self.unpacked_dir.glob("ppt/slideMasters/*.xml"))
if not slide_masters:
if self.verbose:
print("PASSED - No slide masters found")
return True
for slide_master in slide_masters:
try:
# Parse the slide master file
root = lxml.etree.parse(str(slide_master)).getroot()
# Find the corresponding _rels file for this slide master
rels_file = slide_master.parent / "_rels" / f"{slide_master.name}.rels"
if not rels_file.exists():
errors.append(
f" {slide_master.relative_to(self.unpacked_dir)}: "
f"Missing relationships file: {rels_file.relative_to(self.unpacked_dir)}"
)
continue
# Parse the relationships file
rels_root = lxml.etree.parse(str(rels_file)).getroot()
# Build a set of valid relationship IDs that point to slide layouts
valid_layout_rids = set()
for rel in rels_root.findall(
f".//{{{self.PACKAGE_RELATIONSHIPS_NAMESPACE}}}Relationship"
):
rel_type = rel.get("Type", "")
if "slideLayout" in rel_type:
valid_layout_rids.add(rel.get("Id"))
# Find all sldLayoutId elements in the slide master
for sld_layout_id in root.findall(
f".//{{{self.PRESENTATIONML_NAMESPACE}}}sldLayoutId"
):
r_id = sld_layout_id.get(
f"{{{self.OFFICE_RELATIONSHIPS_NAMESPACE}}}id"
)
layout_id = sld_layout_id.get("id")
if r_id and r_id not in valid_layout_rids:
errors.append(
f" {slide_master.relative_to(self.unpacked_dir)}: "
f"Line {sld_layout_id.sourceline}: sldLayoutId with id='{layout_id}' "
f"references r:id='{r_id}' which is not found in slide layout relationships"
)
except (lxml.etree.XMLSyntaxError, Exception) as e:
errors.append(
f" {slide_master.relative_to(self.unpacked_dir)}: Error: {e}"
)
if errors:
print(f"FAILED - Found {len(errors)} slide layout ID validation errors:")
for error in errors:
print(error)
print(
"Remove invalid references or add missing slide layouts to the relationships file."
)
return False
else:
if self.verbose:
print("PASSED - All slide layout IDs reference valid slide layouts")
return True
def validate_no_duplicate_slide_layouts(self):
"""Validate that each slide has exactly one slideLayout reference."""
errors = []
slide_rels_files = list(self.unpacked_dir.glob("ppt/slides/_rels/*.xml.rels"))
for rels_file in slide_rels_files:
try:
root = lxml.etree.parse(str(rels_file)).getroot()
# Find all slideLayout relationships
layout_rels = [
rel
for rel in root.findall(
f".//{{{self.PACKAGE_RELATIONSHIPS_NAMESPACE}}}Relationship"
)
if "slideLayout" in rel.get("Type", "")
]
if len(layout_rels) > 1:
errors.append(
f" {rels_file.relative_to(self.unpacked_dir)}: has {len(layout_rels)} slideLayout references"
)
except Exception as e:
errors.append(
f" {rels_file.relative_to(self.unpacked_dir)}: Error: {e}"
)
if errors:
print("FAILED - Found slides with duplicate slideLayout references:")
for error in errors:
print(error)
return False
else:
if self.verbose:
print("PASSED - All slides have exactly one slideLayout reference")
return True
def validate_notes_slide_references(self):
"""Validate that each notesSlide file is referenced by only one slide."""
errors = []
notes_slide_references = {} # Track which slides reference each notesSlide
# Find all slide relationship files
slide_rels_files = list(self.unpacked_dir.glob("ppt/slides/_rels/*.xml.rels"))
if not slide_rels_files:
if self.verbose:
print("PASSED - No slide relationship files found")
return True
for rels_file in slide_rels_files:
try:
# Parse the relationships file
root = lxml.etree.parse(str(rels_file)).getroot()
# Find all notesSlide relationships
for rel in root.findall(
f".//{{{self.PACKAGE_RELATIONSHIPS_NAMESPACE}}}Relationship"
):
rel_type = rel.get("Type", "")
if "notesSlide" in rel_type:
target = rel.get("Target", "")
if target:
# Normalize the target path to handle relative paths
normalized_target = target.replace("../", "")
# Track which slide references this notesSlide
slide_name = rels_file.stem.replace(
".xml", ""
) # e.g., "slide1"
if normalized_target not in notes_slide_references:
notes_slide_references[normalized_target] = []
notes_slide_references[normalized_target].append(
(slide_name, rels_file)
)
except (lxml.etree.XMLSyntaxError, Exception) as e:
errors.append(
f" {rels_file.relative_to(self.unpacked_dir)}: Error: {e}"
)
# Check for duplicate references
for target, references in notes_slide_references.items():
if len(references) > 1:
slide_names = [ref[0] for ref in references]
errors.append(
f" Notes slide '{target}' is referenced by multiple slides: {', '.join(slide_names)}"
)
for slide_name, rels_file in references:
errors.append(f" - {rels_file.relative_to(self.unpacked_dir)}")
if errors:
print(
f"FAILED - Found {len([e for e in errors if not e.startswith(' ')])} notes slide reference validation errors:"
)
for error in errors:
print(error)
print("Each slide may optionally have its own slide file.")
return False
else:
if self.verbose:
print("PASSED - All notes slide references are unique")
return True
if __name__ == "__main__":
raise RuntimeError("This module should not be run directly.")

View File

@@ -0,0 +1,279 @@
"""
Validator for tracked changes in Word documents.
"""
import subprocess
import tempfile
import zipfile
from pathlib import Path
class RedliningValidator:
"""Validator for tracked changes in Word documents."""
def __init__(self, unpacked_dir, original_docx, verbose=False):
self.unpacked_dir = Path(unpacked_dir)
self.original_docx = Path(original_docx)
self.verbose = verbose
self.namespaces = {
"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
}
def validate(self):
"""Main validation method that returns True if valid, False otherwise."""
# Verify unpacked directory exists and has correct structure
modified_file = self.unpacked_dir / "word" / "document.xml"
if not modified_file.exists():
print(f"FAILED - Modified document.xml not found at {modified_file}")
return False
# First, check if there are any tracked changes by Z.AI to validate
try:
import xml.etree.ElementTree as ET
tree = ET.parse(modified_file)
root = tree.getroot()
# Check for w:del or w:ins tags authored by Z.AI
del_elements = root.findall(".//w:del", self.namespaces)
ins_elements = root.findall(".//w:ins", self.namespaces)
# Filter to only include changes by Z.AI
zai_del_elements = [
elem
for elem in del_elements
if elem.get(f"{{{self.namespaces['w']}}}author") == "Z.AI"
]
zai_ins_elements = [
elem
for elem in ins_elements
if elem.get(f"{{{self.namespaces['w']}}}author") == "Z.AI"
]
# Redlining validation is only needed if tracked changes by Z.AI have been used.
if not zai_del_elements and not zai_ins_elements:
if self.verbose:
print("PASSED - No tracked changes by Z.AI found.")
return True
except Exception:
# If we can't parse the XML, continue with full validation
pass
# Create temporary directory for unpacking original docx
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
# Unpack original docx
try:
with zipfile.ZipFile(self.original_docx, "r") as zip_ref:
zip_ref.extractall(temp_path)
except Exception as e:
print(f"FAILED - Error unpacking original docx: {e}")
return False
original_file = temp_path / "word" / "document.xml"
if not original_file.exists():
print(
f"FAILED - Original document.xml not found in {self.original_docx}"
)
return False
# Parse both XML files using xml.etree.ElementTree for redlining validation
try:
import xml.etree.ElementTree as ET
modified_tree = ET.parse(modified_file)
modified_root = modified_tree.getroot()
original_tree = ET.parse(original_file)
original_root = original_tree.getroot()
except ET.ParseError as e:
print(f"FAILED - Error parsing XML files: {e}")
return False
# Remove Z.AI's tracked changes from both documents
self._remove_zai_tracked_changes(original_root)
self._remove_zai_tracked_changes(modified_root)
# Extract and compare text content
modified_text = self._extract_text_content(modified_root)
original_text = self._extract_text_content(original_root)
if modified_text != original_text:
# Show detailed character-level differences for each paragraph
error_message = self._generate_detailed_diff(
original_text, modified_text
)
print(error_message)
return False
if self.verbose:
print("PASSED - All changes by Z.AI are properly tracked")
return True
def _generate_detailed_diff(self, original_text, modified_text):
"""Generate detailed word-level differences using git word diff."""
error_parts = [
"FAILED - Document text doesn't match after removing Z.AI's tracked changes",
"",
"Likely causes:",
" 1. Modified text inside another author's <w:ins> or <w:del> tags",
" 2. Made edits without proper tracked changes",
" 3. Didn't nest <w:del> inside <w:ins> when deleting another's insertion",
"",
"For pre-redlined documents, use correct patterns:",
" - To reject another's INSERTION: Nest <w:del> inside their <w:ins>",
" - To restore another's DELETION: Add new <w:ins> AFTER their <w:del>",
"",
]
# Show git word diff
git_diff = self._get_git_word_diff(original_text, modified_text)
if git_diff:
error_parts.extend(["Differences:", "============", git_diff])
else:
error_parts.append("Unable to generate word diff (git not available)")
return "\n".join(error_parts)
def _get_git_word_diff(self, original_text, modified_text):
"""Generate word diff using git with character-level precision."""
try:
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
# Create two files
original_file = temp_path / "original.txt"
modified_file = temp_path / "modified.txt"
original_file.write_text(original_text, encoding="utf-8")
modified_file.write_text(modified_text, encoding="utf-8")
# Try character-level diff first for precise differences
result = subprocess.run(
[
"git",
"diff",
"--word-diff=plain",
"--word-diff-regex=.", # Character-by-character diff
"-U0", # Zero lines of context - show only changed lines
"--no-index",
str(original_file),
str(modified_file),
],
capture_output=True,
text=True,
)
if result.stdout.strip():
# Clean up the output - remove git diff header lines
lines = result.stdout.split("\n")
# Skip the header lines (diff --git, index, +++, ---, @@)
content_lines = []
in_content = False
for line in lines:
if line.startswith("@@"):
in_content = True
continue
if in_content and line.strip():
content_lines.append(line)
if content_lines:
return "\n".join(content_lines)
# Fallback to word-level diff if character-level is too verbose
result = subprocess.run(
[
"git",
"diff",
"--word-diff=plain",
"-U0", # Zero lines of context
"--no-index",
str(original_file),
str(modified_file),
],
capture_output=True,
text=True,
)
if result.stdout.strip():
lines = result.stdout.split("\n")
content_lines = []
in_content = False
for line in lines:
if line.startswith("@@"):
in_content = True
continue
if in_content and line.strip():
content_lines.append(line)
return "\n".join(content_lines)
except (subprocess.CalledProcessError, FileNotFoundError, Exception):
# Git not available or other error, return None to use fallback
pass
return None
def _remove_zai_tracked_changes(self, root):
"""Remove tracked changes authored by Z.AI from the XML root."""
ins_tag = f"{{{self.namespaces['w']}}}ins"
del_tag = f"{{{self.namespaces['w']}}}del"
author_attr = f"{{{self.namespaces['w']}}}author"
# Remove w:ins elements
for parent in root.iter():
to_remove = []
for child in parent:
if child.tag == ins_tag and child.get(author_attr) == "Z.AI":
to_remove.append(child)
for elem in to_remove:
parent.remove(elem)
# Unwrap content in w:del elements where author is "Z.AI"
deltext_tag = f"{{{self.namespaces['w']}}}delText"
t_tag = f"{{{self.namespaces['w']}}}t"
for parent in root.iter():
to_process = []
for child in parent:
if child.tag == del_tag and child.get(author_attr) == "Z.AI":
to_process.append((child, list(parent).index(child)))
# Process in reverse order to maintain indices
for del_elem, del_index in reversed(to_process):
# Convert w:delText to w:t before moving
for elem in del_elem.iter():
if elem.tag == deltext_tag:
elem.tag = t_tag
# Move all children of w:del to its parent before removing w:del
for child in reversed(list(del_elem)):
parent.insert(del_index, child)
parent.remove(del_elem)
def _extract_text_content(self, root):
"""Extract text content from Word XML, preserving paragraph structure.
Empty paragraphs are skipped to avoid false positives when tracked
insertions add only structural elements without text content.
"""
p_tag = f"{{{self.namespaces['w']}}}p"
t_tag = f"{{{self.namespaces['w']}}}t"
paragraphs = []
for p_elem in root.findall(f".//{p_tag}"):
# Get all text elements within this paragraph
text_parts = []
for t_elem in p_elem.findall(f".//{t_tag}"):
if t_elem.text:
text_parts.append(t_elem.text)
paragraph_text = "".join(text_parts)
# Skip empty paragraphs - they don't affect content validation
if paragraph_text:
paragraphs.append(paragraph_text)
return "\n".join(paragraphs)
if __name__ == "__main__":
raise RuntimeError("This module should not be run directly.")

721
skills/ppt/references/beamer.md Executable file
View File

@@ -0,0 +1,721 @@
# Route: LaTeX Beamer → PDF (via Tectonic)
Write LaTeX Beamer source, then compile to PDF:
```bash
python3 scripts/pdf.py convert.latex main.tex
python3 scripts/pdf.py convert.latex main.tex --runs 2 # for ToC / refs
```
Tectonic compiles the full Beamer document — all features work: overlays,
TikZ, custom themes, math, transitions, fragile frames, appendix.
---
## 1. Compilation
```bash
# Standard build
python3 scripts/pdf.py convert.latex main.tex
# Two passes (resolves ToC, \ref, section counters in overlays)
python3 scripts/pdf.py convert.latex main.tex --runs 2
# Verbose log (see all Tectonic output)
python3 scripts/pdf.py convert.latex main.tex --keep-logs
```
---
## 2. Beamer Document Structure
### Minimal Working Example
```latex
\documentclass[aspectratio=169, 11pt]{beamer}
\usepackage[fontset=fandol]{ctex} % CJK support (Tectonic auto-downloads)
\usetheme{Madrid}
\title{Introduction to Quantum Computing}
\author{Prof. Zhang}
\institute{Tsinghua University}
\date{\today}
\begin{document}
\begin{frame}
\titlepage
\end{frame}
\begin{frame}{Table of Contents}
\tableofcontents
\end{frame}
\section{Quantum Bits}
\begin{frame}{Quantum States}
\[ |\psi\rangle = \alpha|0\rangle + \beta|1\rangle, \quad |\alpha|^2+|\beta|^2=1 \]
\end{frame}
\end{document}
```
**Core elements:**
- `\documentclass{beamer}` — Presentation document class
- Preamble — Theme, colors, fonts, global settings
- `\begin{frame}...\end{frame}` — Each frame = one slide
---
## 3. Theme System (Complete Reference)
Beamer themes consist of five independent layers that can be freely combined:
### 3.1 Presentation Themes (control overall layout)
| Theme | Features | Suitable For |
|---|---|---|
| `default` | Minimal, no decoration | Formal academic, minimalist |
| `Madrid` | Bottom info bar + section navigation | University courses, academic talks |
| `Berlin` | Top mini-frames + side color blocks | Long technical presentations |
| `Warsaw` | Top circular navigation + gradient title | Structured content |
| `CambridgeUS` | Two-tone minimalist | Math-heavy presentations |
| `Boadilla` | Clean footer | Business, concise style |
| `Singapore` | Top dot navigation | Modern feel, multi-section |
| `AnnArbor` | Yellow-blue dual tone | Michigan style |
| `Antibes` | Blue sidebar tree | Multi-subsection structure |
| `Bergen` | Blue title bar | Formal academic |
| `Copenhagen` | Top bar + navigation | Classic blue scheme |
| `Darmstadt` | Top progress dots | Multi-section structure |
| `Dresden` | Top mini-frames | Similar to Berlin |
| `Frankfurt` | Top dots | Clear section structure |
| `Goettingen` | Right sidebar | Navigation-focused |
| `Luebeck` | Top blue bar | Clean modern |
| `Malmoe` | Minimal title | Content-first |
| `Montpellier` | Top tree navigation | Hierarchical content |
| `Pittsburgh` | No color blocks, minimal | White scheme |
| `Rochester` | Dark title | Dark scheme |
| `Szeged` | Blue title bar | Hungarian style |
```latex
\usetheme{Madrid}
```
### 3.2 Color Themes
| Color Theme | Dominant Color |
|---|---|
| `default` | Dark blue |
| `albatross` | Yellow tones |
| `beaver` | Dark red / maroon |
| `beetle` | Gray-blue |
| `crane` | Orange-yellow |
| `dolphin` | Blue-white |
| `dove` | Gray-white (near monochrome) |
| `fly` | Gray tones |
| `lily` | Red-blue |
| `orchid` | Purple tones |
| `rose` | Pink |
| `seagull` | Gray |
| `seahorse` | Blue-purple |
| `whale` | Deep sea blue |
| `wolverine` | Yellow-blue contrast |
```latex
\usecolortheme{dolphin}
```
### 3.3 Font Themes
```latex
\usefonttheme{default} % Sans-serif (Beamer default)
\usefonttheme{serif} % Serif font (academic feel)
\usefonttheme{structurebold} % Bold structural elements
\usefonttheme{structureitalic} % Italic structural elements
\usefonttheme{structuresmallcapsserif} % Small caps serif
\usefonttheme{professionalfonts} % Keep math fonts unchanged
```
### 3.4 Inner Themes (control list, block, and title styles)
```latex
\useinnertheme{default} % Triangle bullet points
\useinnertheme{circles} % Circle bullet points
\useinnertheme{rectangles} % Square bullet points
\useinnertheme{rounded} % Rounded blocks
\useinnertheme{inmargin} % Margin numbers
```
### 3.5 Outer Themes (control header, footer, and sidebar)
```latex
\useoutertheme{default} % No decoration
\useoutertheme{infolines} % Bottom three-column info
\useoutertheme{miniframes} % Top mini-frame navigation
\useoutertheme{shadow} % Shadow title
\useoutertheme{sidebar} % Sidebar
\useoutertheme{smoothbars} % Gradient top bar
\useoutertheme{smoothtree} % Gradient tree
\useoutertheme{split} % Top-bottom split
\useoutertheme{tree} % Tree navigation
```
### 3.6 Custom Colors
```latex
\definecolor{myblue}{HTML}{2B5EA7}
\definecolor{mygray}{HTML}{F0F0F0}
\setbeamercolor{frametitle}{bg=myblue, fg=white}
\setbeamercolor{structure}{fg=myblue}
\setbeamercolor{block title}{bg=myblue!85, fg=white}
\setbeamercolor{block body}{bg=myblue!8}
\setbeamercolor{alerted text}{fg=red!70!black}
\setbeamercolor{title}{fg=white}
\setbeamercolor{subtitle}{fg=white!80}
```
### 3.7 Common Template Customizations
```latex
% Remove navigation symbols (almost always needed)
\setbeamertemplate{navigation symbols}{}
% Custom footer (frame number)
\setbeamertemplate{footline}{%
\hfill\insertframenumber/\inserttotalframenumber\hspace{1em}\vspace{0.5em}
}
% Custom bullet points
\setbeamertemplate{itemize item}{\textbullet}
\setbeamertemplate{itemize subitem}{--}
% Logo (bottom-right corner)
\logo{\includegraphics[height=0.7cm]{logo.png}}
% Rounded blocks
\setbeamertemplate{blocks}[rounded][shadow=true]
```
---
## 4. Overlays & Stepwise Reveal
Tectonic fully supports all overlay syntax — rendered as separate pages in the PDF.
### 4.1 Basic Overlay Specifications
```latex
\item<1-> % Show from layer 1, persist
\item<2-> % Show from layer 2
\item<1-3> % Show on layers 1 to 3 only
\item<2> % Show on layer 2 only
\item<-3> % Show before layer 3
```
### 4.2 \pause — Simplest Stepwise Reveal
```latex
\begin{frame}{Research Workflow}
Data collection phase
\pause
Feature engineering phase
\pause
Model training phase
\end{frame}
```
### 4.3 List Stepwise Reveal
```latex
\begin{frame}{Research Contributions}
\begin{itemize}
\item<1-> Propose a novel loss function
\item<2-> Prove theoretical convergence
\item<3-> Outperform SOTA on five benchmarks
\end{itemize}
\end{frame}
```
### 4.4 \only vs \uncover vs \visible
```latex
% \only: no space reserved (causes layout jump)
\only<1>{Step one explanation}
\only<2>{Step two explanation}
% \uncover: reserves space but transparent (recommended, stable layout)
\uncover<2->{Follow-up steps explanation}
% \visible: reserves space but not rendered
\visible<3->{Step three}
```
### 4.5 \alert — Highlight Specific Layers
```latex
\begin{frame}{Key Findings}
\begin{itemize}
\item \alert<1>{Accuracy improved by 13\%}
\item \alert<2>{Inference speed improved 2.4x}
\item \alert<3>{Memory reduced by 40\%}
\end{itemize}
\end{frame}
```
### 4.6 \textcolor & Conditional Content
```latex
\begin{frame}{Comparison}
Baseline method: \textcolor{red}{82\%}\\
\only<2->{Our method: \textcolor{green!60!black}{\textbf{93\%}}}
\end{frame}
```
### 4.7 Block Overlays
```latex
\begin{frame}{Analysis}
\begin{block}<1-2>{Problem Definition}
Formal description ...
\end{block}
\begin{block}<2->{Solution}
Core approach ...
\end{block}
\end{frame}
```
---
## 5. Content Layout Templates
### 5.1 Block Series (Three Styles)
```latex
\begin{frame}{Core Findings}
\begin{block}{Main Conclusion}
The new method outperforms baselines in both accuracy and speed.
\end{block}
\begin{alertblock}{Caveats}
Results are validated on specific datasets; generalization needs further study.
\end{alertblock}
\begin{exampleblock}{Example}
Achieved 99.1\% accuracy on the MNIST dataset.
\end{exampleblock}
\end{frame}
```
### 5.2 Column Layout
```latex
\begin{frame}{Experimental Comparison}
\begin{columns}[T] % [T] top-aligned
\column{0.48\textwidth}
\begin{block}{Baseline Method}
Accuracy: 82\% \\
Time: 3.2 hours
\end{block}
\column{0.48\textwidth}
\begin{block}{Our Method}
Accuracy: \textbf{91\%} \\
Time: \textbf{1.7 hours}
\end{block}
\end{columns}
\end{frame}
```
Column alignment options: `[T]` top-aligned · `[c]` centered · `[b]` bottom-aligned
### 5.3 Math Formula Frame
```latex
\begin{frame}{Loss Function}
\begin{equation*}
\mathcal{L} = -\sum_{i=1}^{N} y_i \log \hat{y}_i + \lambda \|\theta\|_2^2
\end{equation*}
\begin{itemize}
\item $y_i$: Ground truth label
\item $\hat{y}_i$: Predicted probability
\item $\lambda$: Regularization coefficient
\end{itemize}
\end{frame}
```
### 5.4 Theorem Environment
```latex
\begin{frame}{Convergence Theorem}
\begin{theorem}[Convergence Rate]
Under Lipschitz conditions, gradient descent converges at $O(1/\sqrt{T})$.
\end{theorem}
\begin{proof}
Follows from Lipschitz continuity and step size $\eta = 1/L$.\qed
\end{proof}
\begin{corollary}
The stochastic gradient variant converges in expectation at $O(1/\sqrt{T})$.
\end{corollary}
\end{frame}
```
### 5.5 Table Frame
```latex
\begin{frame}{Performance Comparison}
\centering
\begin{tabular}{lcc}
\toprule
Method & Accuracy & Time(s) \\
\midrule
SVM & 0.85 & 120 \\
Random Forest & 0.89 & 65 \\
\textbf{Ours} & \textbf{0.93} & \textbf{42} \\
\bottomrule
\end{tabular}
\end{frame}
```
### 5.6 TikZ Flowchart
TikZ is fully supported in Tectonic — no pre-rendering needed:
```latex
\begin{frame}{Algorithm Pipeline}
\centering
\begin{tikzpicture}[
node distance=2cm,
box/.style={rectangle, rounded corners=4pt, draw=myblue, thick,
fill=myblue!10, minimum width=2.2cm, minimum height=0.9cm, font=\small},
arr/.style={-Stealth, thick, myblue}
]
\node[box] (A) {Input Data};
\node[box, right of=A] (B) {Feature Extraction};
\node[box, right of=B] (C) {Model Inference};
\node[box, right of=C] (D) {Output Results};
\draw[arr] (A) -- (B);
\draw[arr] (B) -- (C);
\draw[arr] (C) -- (D);
\end{tikzpicture}
\end{frame}
```
### 5.7 Code Display Frame
```latex
\begin{frame}[fragile]{Training Loop} % [fragile] is required
\begin{verbatim}
for epoch in range(epochs):
for batch in dataloader:
optimizer.zero_grad()
loss = model(batch)
loss.backward()
optimizer.step()
\end{verbatim}
\end{frame}
```
Or use `listings` for syntax highlighting (more polished):
```latex
\usepackage{listings}
\lstset{
basicstyle=\ttfamily\small,
keywordstyle=\color{blue}\bfseries,
commentstyle=\color{gray},
backgroundcolor=\color{gray!5},
numbers=left, numberstyle=\tiny\color{gray},
frame=single, framerule=0.5pt
}
\begin{frame}[fragile]{Python Code}
\begin{lstlisting}[language=Python]
def train(model, dataloader):
for batch in dataloader:
loss = model(batch)
loss.backward()
\end{lstlisting}
\end{frame}
```
### 5.8 Image Frame
```latex
\begin{frame}{System Architecture}
\centering
\includegraphics[width=0.85\textwidth]{figures/architecture.png}
\captionof{figure}{End-to-end training pipeline}
\end{frame}
```
### 5.9 Custom Checklist Frame
```latex
\begin{frame}{Summary of Contributions}
\begin{itemize}
\item[\checkmark] New method proposed: ...
\item[\checkmark] Theoretical proof: ...
\item[\checkmark] Experimental validation: ...
\item[$\square$] Future work: ...
\end{itemize}
\end{frame}
```
---
## 6. Advanced Features
### 6.1 Progress Bar (Manual Implementation)
```latex
% Define in preamble
\definecolor{progressbar}{HTML}{2B5EA7}
\setbeamertemplate{footline}{
\begin{beamercolorbox}[wd=\paperwidth,ht=2pt]{progressbar}
\rule{\dimexpr\paperwidth*\insertframenumber/\inserttotalframenumber}{2pt}
\end{beamercolorbox}
\vspace{2pt}
\hfill\tiny\insertframenumber/\inserttotalframenumber\hspace{1em}\vspace{3pt}
}
```
### 6.2 Section Title Pages (Automatic)
```latex
% Add in preamble — auto-inserts a section title page before each \section
\AtBeginSection[]{
\begin{frame}
\vfill
\centering
\begin{beamercolorbox}[sep=8pt,center,shadow=true,rounded=true]{title}
\usebeamerfont{title}\insertsectionhead\par
\end{beamercolorbox}
\vfill
\end{frame}
}
```
### 6.3 Handout Mode
```latex
% Generate overlay-free handout version (only final state of each frame)
\documentclass[handout, aspectratio=169]{beamer}
```
Combine with `pgfpages` to compress multiple frames onto one page:
```latex
\usepackage{pgfpages}
\pgfpagesuselayout{4 on 1}[a4paper, border shrink=5mm]
```
### 6.4 Frame Reuse (\againframe)
```latex
\begin{frame}[label=keyresult]{Key Result}
Accuracy improved by 13\%.
\end{frame}
% Show again at any later point
\againframe{keyresult}
```
### 6.5 Appendix (Excluded from Total Page Count)
```latex
\appendix
\begin{frame}{Appendix: Detailed Derivation}
% Backup slides for Q&A
\end{frame}
```
### 6.6 Speaker Notes
```latex
\begin{frame}{Main Conclusions}
\begin{itemize}
\item Conclusion one
\item Conclusion two
\end{itemize}
\note{
Emphasize the data supporting conclusion one.\\
Anticipate questions about dataset size.
}
\end{frame}
```
Output PDF with notes: add in preamble:
```latex
\setbeameroption{show notes on second screen=right}
```
### 6.7 Widescreen Aspect Ratios
```latex
\documentclass[aspectratio=169]{beamer} % 16:9 (recommended)
\documentclass[aspectratio=1610]{beamer} % 16:10
\documentclass[aspectratio=43]{beamer} % 4:3 (traditional)
\documentclass[aspectratio=141]{beamer} % 1.41:1 (A4)
```
---
## 7. Complete Template (Academic Presentation, 16:9, with CJK Support)
```latex
\documentclass[aspectratio=169, 11pt]{beamer}
\usepackage[fontset=fandol]{ctex}
\usepackage{amsmath, amssymb, mathtools}
\usepackage{booktabs}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, positioning, shapes.geometric}
% -- Theme ---------------------------------------------------------------
\usetheme{Madrid}
\usecolortheme{dolphin}
\usefonttheme{professionalfonts}
\setbeamertemplate{navigation symbols}{}
% -- Colors --------------------------------------------------------------
\definecolor{myblue}{HTML}{2B5EA7}
\setbeamercolor{frametitle}{bg=myblue, fg=white}
\setbeamercolor{structure}{fg=myblue}
\setbeamercolor{block title}{bg=myblue!85, fg=white}
\setbeamercolor{block body}{bg=myblue!8}
% -- Auto section title page ---------------------------------------------
\AtBeginSection[]{
\begin{frame}
\vfill\centering
\begin{beamercolorbox}[sep=8pt,center,rounded=true]{title}
\usebeamerfont{title}\insertsectionhead\par
\end{beamercolorbox}
\vfill
\end{frame}
}
% -- Metadata ------------------------------------------------------------
\title{Paper Title}
\subtitle{Subtitle}
\author{Author Name}
\institute{Affiliation}
\date{\today}
% ========================================================================
\begin{document}
\begin{frame}
\titlepage
\end{frame}
\begin{frame}{Table of Contents}
\tableofcontents
\end{frame}
\section{Introduction}
\begin{frame}{Research Background}
\begin{itemize}
\item<1-> Importance of the problem
\item<2-> Limitations of existing methods
\item<3-> Contributions of this work
\end{itemize}
\end{frame}
\section{Method}
\begin{frame}{Core Formula}
\begin{equation*}
\mathcal{L} = -\sum_{i=1}^{N} y_i \log \hat{y}_i + \lambda \|\theta\|_2^2
\end{equation*}
\begin{itemize}
\item $y_i$: Ground truth label
\item $\hat{y}_i$: Predicted probability
\item $\lambda$: Regularization coefficient
\end{itemize}
\end{frame}
\begin{frame}{Method Comparison}
\begin{columns}[T]
\column{0.48\textwidth}
\begin{block}{Baseline Method}
Accuracy: 82\% \\
Time: 3.2 hours
\end{block}
\column{0.48\textwidth}
\begin{block}{Our Method}
Accuracy: \textbf{91\%} \\
Time: \textbf{1.7 hours}
\end{block}
\end{columns}
\end{frame}
\section{Experiments}
\begin{frame}{Performance Comparison}
\centering
\begin{tabular}{lcc}
\toprule
Method & Accuracy & Time(s) \\
\midrule
SVM & 0.85 & 120 \\
Random Forest & 0.89 & 65 \\
\textbf{Ours} & \textbf{0.93} & \textbf{42} \\
\bottomrule
\end{tabular}
\end{frame}
\section{Conclusion}
\begin{frame}{Summary}
\begin{itemize}
\item[\checkmark] Contribution 1: Proposed new method
\item[\checkmark] Contribution 2: Theoretical proof
\item[\checkmark] Contribution 3: Experimental validation
\end{itemize}
\begin{block}{Future Work}
Extend to larger-scale datasets and explore cross-domain generalization.
\end{block}
\end{frame}
\begin{frame}
\centering\Large Thank You!\\[0.8em]
\normalsize Questions Welcome
\end{frame}
\end{document}
```
Compile:
```bash
python3 scripts/pdf.py convert.latex main.tex --runs 2
```
---
## 8. Common Issues & Fixes
| Issue | Cause | Fix |
|---|---|---|
| CJK characters display as boxes | Missing CJK font package | Add `\usepackage[fontset=fandol]{ctex}` |
| `??` appears in ToC or references | Only compiled once | Add `--runs 2` |
| `[fragile]` missing error | verbatim/lstlisting frame | Add `[fragile]` after `\begin{frame}` |
| Overlay not working | Forgot `\pause` or `<n->` in frame | Check overlay specification syntax |
| TikZ compilation failure | Missing tikzlibrary | Add `\usetikzlibrary{...}` |
| Math font distortion | Missing professionalfonts | Add `\usefonttheme{professionalfonts}` |
| Frame exceeds one page (content overflow) | Too much content | Add `[allowframebreaks]` or split frame |
---
## 9. Dependencies
| Tool | Purpose |
|---|---|
| `scripts/tectonic` | LaTeX compilation engine (local binary) |
| `scripts/pdf.py convert.latex` | Tectonic wrapper with log filtering + PDF stats |

342
skills/ppt/references/latex.md Executable file
View File

@@ -0,0 +1,342 @@
# Route 3: Academic & Scientific PDF via LaTeX
Produce publication-grade PDFs from `.tex` source files compiled with Tectonic. Suited for academic papers, theses, mathematical manuscripts, IEEE/ACM-format submissions, and any document where the user explicitly requests LaTeX.
**Guiding principle**: when someone asks for "a LaTeX PDF," they expect a polished, professional result — not a bare-minimum compilation.
---
## Environment Preparation
The binary of Tectonic lands at `scripts/tectonic`.
### Compilation — Always Use the Wrapper Script
All compilations **must** go through `scripts/pdf.py convert.latex`. It handles:
- Stripping noisy package-download logs
- Filtering progress chatter
- Surfacing genuine errors and warnings
- Reporting PDF statistics (file size, page count, word estimate, image tally)
**Do not invoke Tectonic directly.**
```bash
# One-pass build
python3 scripts/pdf.py convert.latex main.tex
# Two passes (resolves cross-references)
python3 scripts/pdf.py convert.latex main.tex --runs 2
# Verbose mode (retains full log output)
python3 scripts/pdf.py convert.latex main.tex --keep-logs
```
---
## Pre-Writing Planning
Before touching `.tex` code, determine the document's category and let that shape your approach.
### Recognising the Document Type
| Type | Typical outputs | Key concern |
|------|----------------|-------------|
| **Scholarly** | Journal articles, conference proceedings, regulatory specs | Rigorous adherence to academic conventions; bibliography accuracy |
| **Utilitarian** | Technical reports, reference manuals, product specs | Pack maximum information while preserving scannability |
| **Persuasive** | Funding proposals, pitch documents, project roadmaps | Clean professionalism throughout, with one or two visual high-points (title page, KPI dashboards) |
| **Expressive** | Design portfolios, brand guidebooks, showcases | Bold typographic and chromatic choices; deliberate rule-breaking that amplifies impact |
### Fallback Aesthetic (No Style Specified)
When the user gives no visual direction, apply a **measured, high-craft** system:
1. **Contrast** — clear figure-ground separation; headings visually distinct from running text
2. **Hierarchy** — establish reading order through deliberate variation in size, weight, and hue
3. **White space** — ample margins and leading to let the page breathe
4. **Coherence** — one typeface family, one accent colour, one spacing rhythm
#### Enrichment Elements (Add Proactively When Appropriate)
- **Decorative**: shaded callout boxes, sidebars, comparison panels → `tcolorbox`
- **Scholarly**: theorem / definition / proof environments → `amsthm` + `tcolorbox`; process diagrams → TikZ
- **Page furniture**: running headers and footers → `fancyhdr`; chapter openers → `titlesec`
Introduce these components on your own initiative whenever the content benefits — don't wait to be told.
---
## Mandatory Rules
### Rule 1 — Every Build Diagnostic Demands Attention
The wrapper classifies compiler output into three tiers:
| Tier | Impact | Required response |
|------|--------|-------------------|
| **Errors** | Build aborts | Resolve before anything else |
| **Layout defects** | Overfull / underfull boxes, unavailable font shapes, missing glyphs | Repair prior to delivery |
| **Advisories** | Remaining warnings | Assess individually; fix whenever feasible |
**Never acceptable**: shrugging off warnings with "they don't affect the final PDF." Every diagnostic merits investigation.
### Rule 2 — Modular Files for Larger Works
A single generation turn can comfortably handle roughly **500 lines** of TeX.
**When to split**:
- Anticipated output exceeds 5 pages, **or**
- Three or more heavyweight elements are present (wide tables, block equations, TikZ graphics)
Stitch modules together with `\input{chapter1}`, `\input{chapter2}`, etc.
### Rule 3 — Foundation Preamble
```latex
\documentclass{article}
% Essentials
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{geometry}
\usepackage{amsmath} % Load before hyperref
% hyperref — ALWAYS last among content packages
\usepackage[
colorlinks=true,
linkcolor=blue,
citecolor=darkgray,
urlcolor=blue,
bookmarks=true,
bookmarksnumbered=true,
unicode=true
]{hyperref}
% Page dimensions
\geometry{a4paper, top=2.5cm, bottom=2.5cm, left=3cm, right=2.5cm}
% CV variant: \geometry{a4paper, margin=1.5cm}
% Superscript citation numbers (scholarly convention)
\usepackage[numbers,super,sort&compress]{natbib}
\bibliographystyle{unsrtnat}
% Commonly needed extras
\usepackage{tcolorbox}
\usepackage{colortbl}
\usepackage{booktabs}
\usepackage{enumitem}
```
**hyperref positioning**: it must load after virtually every other package to avoid option clashes.
### Rule 4 — TeX Source Hygiene
**Prohibited patterns**:
- Emoji glyphs (no native LaTeX engine supports them)
- Markdown `*asterisk*` formatting (generates compile-time errors)
**Use instead**:
```latex
\textbf{bold text}
\emph{emphasised text}
```
These are frequent model-generation slips — catch them proactively.
### Rule 5 — Multi-Language & Font Handling
- `babel` and `polyglossia` are incompatible — load only one
- When using `polyglossia`, ensure `amsmath` appears earlier in the preamble
- Tectonic downloads standard LaTeX typefaces automatically (Latin Modern, etc.)
- To reference system-installed fonts via `\setmainfont{}`, first probe with `fc-list :lang=ar`
- Broadly available choices: DejaVu, Noto typeface families
### Rule 6 — Clickable Navigation Is Non-Negotiable
Interactive navigation is a baseline professional expectation.
#### 6.1 Table of Contents
```latex
\tableofcontents % Entries are auto-linked courtesy of hyperref
\listoffigures
\listoftables
```
#### 6.2 Internal Cross-References
**Attach labels** right after each numbered element:
```latex
\section{Background}\label{sec:bg}
\begin{figure}[htbp]
\includegraphics{...}
\caption{Overview diagram}\label{fig:overview}
\end{figure}
\begin{table}[htbp]
\caption{Benchmark results}\label{tab:bench}
...
\end{table}
\begin{equation}\label{eq:energy}
E = mc^2
\end{equation}
```
**Cite these labels** (each produces a live hyperlink):
```latex
As noted in Section~\ref{sec:bg}...
Figure~\ref{fig:overview} illustrates...
Table~\ref{tab:bench} summarises...
Equation~\eqref{eq:energy} yields... % \eqref auto-wraps in parentheses
See page~\pageref{sec:bg}...
```
**Good habits**:
- Place a non-breaking space `~` before `\ref` to avoid orphaned line breaks
- Prefer `\eqref{}` for equations (auto-wraps the number in parentheses)
- Adopt a consistent label-prefix convention: `sec:`, `fig:`, `tab:`, `eq:`, `lst:`
#### 6.3 Bibliography
**Superscript numerals (preferred academic style)**:
```latex
\usepackage[numbers,super,sort&compress]{natbib}
\bibliographystyle{unsrtnat}
Prior work\cite{smith2023} shows... % → shows^[1]
Several studies\cite{a,b,c} agree... % → agree^[13]
\bibliography{refs}
```
**Numeric bracket alternative**:
```latex
\usepackage[numbers]{natbib}
\bibliographystyle{plainnat}
\cite{smith2023} % [1]
\citep{smith2023} % (Smith, 2023)
\citet{smith2023} % Smith (2023)
```
**biblatex pathway**:
```latex
\usepackage[backend=biber,style=numeric-comp]{biblatex}
\addbibresource{refs.bib}
Per~\cite{smith2023}...
\printbibliography
```
#### 6.4 External Links
```latex
\url{https://example.com}
\href{https://example.com}{Visible label}
\href{mailto:a@b.com}{a@b.com}
```
#### 6.5 PDF Metadata & Outline
```latex
\hypersetup{
pdftitle={Document Title},
pdfauthor={Author Name},
pdfsubject={Topic},
pdfkeywords={keyword1, keyword2}
}
```
Bookmark trees are auto-generated from `\section` / `\chapter` hierarchy.
#### 6.6 Why Multiple Passes Matter
Label resolution requires at least two compilation passes:
```bash
# Resolve section / figure / table labels
python3 scripts/pdf.py convert.latex main.tex --runs 2
# Also resolves bibliography back-references
python3 scripts/pdf.py convert.latex main.tex --runs 3
```
If `??` placeholders persist after two passes, verify that every `\label` string has an exact `\ref` match.
#### 6.7 Navigation Troubleshooting
| Observation | Root cause | Resolution |
|-------------|-----------|------------|
| `??` in place of numbers | Only a single pass was run | Recompile with `--runs 2` |
| All links render in black | hyperref colour options omitted | Enable `colorlinks=true` |
| TOC items are not clickable | hyperref package missing | Load the package |
| `[?]` beside citations | `.bib` path incorrect or biber step skipped | Confirm path; rebuild |
| Bookmark pane empty | `bookmarks` option set to false | Switch to `bookmarks=true` |
---
## Package Catalogue
### Foundational
- `hyperref` (Rule 3)
- `geometry` (Rule 3)
- `listings``\lstset{basicstyle=\ttfamily\small, numbers=left, backgroundcolor=\color{gray!5}}`
- `enumitem``\setlist[itemize]{itemsep=0.3em, leftmargin=1.5em}`
### Tabular
`booktabs` · `longtable` · `multirow` · `array` · `colortbl`
### Visual & Charting
`tikz` · `pgfplots` · `float` · `wrapfig` · `subfig` / `subcaption`
### International & Typography
`fontspec` (XeLaTeX / LuaLaTeX) · `ctex`
### Mathematical
`amsmath` · `amssymb` · `amsthm` · `natbib` · `biblatex` · `siunitx`
### Algorithmic & Domain-Specific
`algorithm` + `algpseudocode` · `chemfig`
### Page Design
`tcolorbox` · `fancyhdr` · `titlesec` · `tocloft` · `multicol` · `setspace` · `microtype` · `parskip` · `adjustbox` · `marginnote`
### Code Listings
`listings` · `minted` (depends on Pygments)
---
## Scripts & Backends
| Script | Purpose |
|--------|---------|
| `pdf.py convert.latex` | Tectonic wrapper — log sanitisation, error highlighting, PDF metrics |
| Engine | Notes |
|--------|-------|
| Tectonic | Stand-alone LaTeX engine; packages are fetched transparently on demand |
---
## Operational Notes
### CJK Without Manual Font Setup
Tectonic resolves CJK font bundles on the fly — zero manual installation:
```latex
\usepackage{ctex} % Tectonic pulls the font files automatically
```
### Cold-Start Latency
The very first compilation of a new document triggers package downloads:
- Initial build: 15 min (depends on network speed)
- Repeat builds with warm cache: 1030 s
### Working Without Internet
Previously fetched packages are stored under `~/.cache/Tectonic/`. When offline, only cached packages are available; attempting to use a new one will fail.
### Tectonic vs a Full TeX Live Installation
| Dimension | Tectonic | Traditional pdflatex |
|-----------|----------|---------------------|
| Package acquisition | On-demand, transparent | Manual via `tlmgr` |
| Multi-pass compilation | Handled by the engine | Explicit re-invocations required |
| Reference resolution | Automatic | Requires bibtex/biber cycles |
| Disk footprint | Single binary | Full TeX Live ≈ 4 GB |

View File

@@ -0,0 +1,73 @@
% ========================================================================
% Paper Presentation Navigation for Beamer
% ========================================================================
% Usage: \input{paper-navbar.tex} in the preamble (after \usetheme and color definitions)
%
% Provides:
% - Top navigation bar: section names + miniframe dots (no subsection row)
% - Bottom footer: Author | Paper Title | Journal, Year | Page number
% - All colors follow myblue (adapts to any Preset Color Palette)
%
% Prerequisites (must be defined before \input):
% - \definecolor{myblue}{HTML}{...} (from chosen Preset Color Palette)
% - \useoutertheme{miniframes} (required for top navigation)
%
% Paper metadata setup (in preamble, after \input):
% \title[Short Title]{Full Title}
% \author[Author (Affiliation)]{Full Author List}
% \date[Journal Name, Year]{} % leave empty if no journal: \date[]{}
% ========================================================================
% ── Unify header and footer colors (follow myblue) ─────────────────────
% Top navbar: light tint of theme color
\setbeamercolor{section in head/foot}{bg=myblue!15, fg=myblue!80!black}
\setbeamercolor{subsection in head/foot}{bg=myblue!15, fg=myblue!80!black}
% Bottom footer: author/journal/page use light tint, title uses mid tint
\setbeamercolor{author in head/foot}{bg=myblue!15, fg=myblue!80!black}
\setbeamercolor{title in head/foot}{bg=myblue!30, fg=white}
\setbeamercolor{date in head/foot}{bg=myblue!15, fg=myblue!80!black}
% ── Remove navigation symbols ─────────────────────────────────────────
\setbeamertemplate{navigation symbols}{}
% ── Compress miniframes + remove subsection empty row ─────────────────
\makeatletter
\let\beamer@writeslidentry@miniframeson=\beamer@writeslidentry
\def\beamer@writeslidentry@miniframesoff{%
\expandafter\beamer@ifempty\expandafter{\beamer@framestartpage}{}%
{\addtocontents{nav}{\protect\headcommand{%
\protect\beamer@partpages{\the\c@page}{\the\c@page}}}}}
\newcommand*{\miniframeson}{\let\beamer@writeslidentry=\beamer@writeslidentry@miniframeson}
\newcommand*{\miniframesoff}{\let\beamer@writeslidentry=\beamer@writeslidentry@miniframesoff}
\beamer@compresstrue
\makeatother
% ── Top navigation: section names + miniframe dots, no subsection row ──
\setbeamertemplate{headline}{%
\begin{beamercolorbox}[colsep=1.5pt]{upper separation line head}
\end{beamercolorbox}
\begin{beamercolorbox}{section in head/foot}
\vskip2pt\insertnavigation{\paperwidth}\vskip2pt
\end{beamercolorbox}%
}
% ── Bottom footer: Author | Paper Title | Journal | Page ──────────────
\makeatletter
\setbeamertemplate{footline}{%
\leavevmode%
\hbox{%
\begin{beamercolorbox}[wd=.25\paperwidth,ht=2.5ex,dp=1ex,center]{author in head/foot}%
\usebeamerfont{author in head/foot}\insertshortauthor
\end{beamercolorbox}%
\begin{beamercolorbox}[wd=.42\paperwidth,ht=2.5ex,dp=1ex,center]{title in head/foot}%
\usebeamerfont{title in head/foot}\insertshorttitle
\end{beamercolorbox}%
\begin{beamercolorbox}[wd=.22\paperwidth,ht=2.5ex,dp=1ex,center]{date in head/foot}%
\usebeamerfont{date in head/foot}\insertshortdate
\end{beamercolorbox}%
\begin{beamercolorbox}[wd=.11\paperwidth,ht=2.5ex,dp=1ex,right]{date in head/foot}%
\usebeamerfont{date in head/foot}\insertframenumber{}/\inserttotalframenumber\kern2em
\end{beamercolorbox}%
}%
}
\makeatother

View File

@@ -0,0 +1,151 @@
% ========================================================================
% Progress Navigation Bar for Beamer
% ========================================================================
% Usage: \input{progress-navbar.tex} in the preamble (after \usetheme)
%
% Features:
% - Dynamic equal-width boxes: each box = (paperwidth - 50pt) / total frames
% - Three-level symbols: ≡ (home), 1/2/3 (section), ◆ (subsection), - (slide)
% - Teal progress coloring: visited = teal!60 fill, unvisited = hollow
% - Clickable hyperlinks on every box
% - Automatic section/subsection title pages
% - Requires --runs 2 for correct width calculation
%
% Customization:
% - Change "teal!60" to any color (e.g. myblue!60) for different themes
% - Change "teal" in \color{teal}\hrule for the top separator line
% ========================================================================
\makeatletter
% ── Auto section/subsection title pages ─────────────────────────────────
\AtBeginSection[]{\frame{\sectionpage}}
\AtBeginSubsection[]{\frame{\subsectionpage}}
% ── Lengths and counters ────────────────────────────────────────────────
\newlength{\my@unitwidth}
\newlength{\my@tempsize}
\newcounter{my@sectnum}
% ── Helper: extract last digit of section number ────────────────────────
\newcommand{\my@lastdigit}[1]{%
\loop\ifnum\value{#1}>9\addtocounter{#1}{-10}\repeat
{\normalfont\arabic{#1}}%
}
% ── Box primitives ──────────────────────────────────────────────────────
\newcommand\my@fixedbox[2]{%
\makebox[#1]{\rule[-1ex]{0pt}{3.25ex}#2}%
}
\newcommand\my@colorbox[3]{%
{\setlength{\fboxsep}{0pt}\colorbox{#1}{\my@fixedbox{#2}{#3}}}%
}
% ── Level marker: b=section, m=subsection, s=slide ─────────────────────
\def\my@temptext{}
\def\my@level{s}
\newcommand{\my@navbox}[1][]{%
\if\relax\detokenize{#1}\relax
\def\my@tempbox{\my@fixedbox}%
\else
\def\my@tempbox{\my@colorbox{#1}}%
\fi
\if b\my@level
\def\my@temptext{\my@lastdigit{my@sectnum}}%
\fi
\if m\my@level
\def\my@temptext{$\diamond$}%
\fi
\if s\my@level
\def\my@temptext{$-$}%
\fi
\my@tempbox{\my@unitwidth}{\my@temptext}%
}
% ── Navigation box templates (home / done / todo) ──────────────────────
\defbeamertemplate{navigation box}{home}{%
\my@colorbox{teal!60}{\my@unitwidth}{$\equiv$}%
}
\defbeamertemplate{navigation box}{done}{%
\my@navbox[teal!60]%
}
\defbeamertemplate{navigation box}{todo}{%
\my@navbox
}
% ── Box dispatch commands ──────────────────────────────────────────────
\newcommand{\my@bigbox}{\gdef\my@level{b}\usebeamertemplate{navigation box}}
\newcommand{\my@medbox}{\gdef\my@level{m}\usebeamertemplate{navigation box}}
\newcommand{\my@smallbox}{\gdef\my@level{s}\usebeamertemplate{navigation box}}
% ── Hook into Beamer's navigation infrastructure ──────────────────────
\renewcommand{\sectionentry}[5]{\gdef\my@currentbox{big}\setcounter{my@sectnum}{#1}}
\renewcommand{\beamer@subsectionentry}[5]{\gdef\my@currentbox{med}}
\renewcommand{\slideentry}[6]{%
\def\my@temp@i{1/1}%
\def\my@temp@ii{#4}%
% Default: assume done
\ifx\my@temp@i\my@temp@ii
\setbeamertemplate{navigation box}[home]%
\else
\setbeamertemplate{navigation box}[done]%
\fi
% Override to todo if this slide is ahead of current position
\ifnum\c@section<#1%
\setbeamertemplate{navigation box}[todo]%
\else
\ifnum\c@section=#1\ifnum\c@subsection<#2%
\setbeamertemplate{navigation box}[todo]%
\else
\ifnum\c@subsection=#2\ifnum\c@subsectionslide<#3%
\setbeamertemplate{navigation box}[todo]%
\fi\fi
\fi\fi
\fi
% Dispatch to correct level box
\def\my@test@big{big}%
\def\my@test@med{med}%
\ifx\my@temp@i\my@temp@ii
\beamer@link(#4){\my@bigbox}%
\else
\ifx\my@currentbox\my@test@big
\beamer@link(#4){\my@bigbox}%
\else\ifx\my@currentbox\my@test@med
\beamer@link(#4){\my@medbox}%
\else
\beamer@link(#4){\my@smallbox}%
\fi\fi
\fi
\gdef\my@currentbox{small}%
}
% ── Footline template ─────────────────────────────────────────────────
\defbeamertemplate{footline}{progress}
{%
% Dynamic width: divide available space equally among all frames
\ifnum\inserttotalframenumber>0
\setlength{\my@unitwidth}{\dimexpr(\paperwidth - 50pt)/\inserttotalframenumber\relax}%
\else
\setlength{\my@unitwidth}{20pt}%
\fi
{\color{teal}\hrule}%
\hbox to \paperwidth{%
\hbox to \dimexpr\paperwidth - 50pt\relax{%
\kern2pt{\normalfont\dohead}\hfill
}%
\hbox to 50pt{%
\hfill{\normalfont\insertframenumber{}/\inserttotalframenumber}\kern4pt
}%
}%
}
% ── Activate ──────────────────────────────────────────────────────────
\setbeamertemplate{navigation symbols}{}
\setbeamertemplate{footline}[progress]
\makeatother

Binary file not shown.

1337
skills/ppt/scripts/html2pptx.js Executable file

File diff suppressed because it is too large Load Diff

512
skills/ppt/scripts/inventory.py Executable file
View File

@@ -0,0 +1,512 @@
#!/usr/bin/env python3
"""
Extract structured text content from PowerPoint presentations.
Usage:
python inventory.py input.pptx output.json [--issues-only]
"""
import argparse
import json
import sys
from pathlib import Path
from typing import Any, Dict, List, Optional
from pptx import Presentation
from pptx.enum.text import PP_ALIGN
from pptx.shapes.base import BaseShape
# Public type alias used by replace.py: slide_id -> {shape_id -> ShapeData}
InventoryData = Dict[str, Dict[str, "ShapeData"]]
_EMU = 914400 # EMUs per inch
_BULLET_NS = "{http://schemas.openxmlformats.org/drawingml/2006/main}"
_ALIGN_MAP = {
PP_ALIGN.CENTER: "CENTER",
PP_ALIGN.RIGHT: "RIGHT",
PP_ALIGN.JUSTIFY: "JUSTIFY",
}
def _is_cjk(ch: str) -> bool:
"""True for full-width CJK characters (Chinese, Japanese, Korean, full-width forms)."""
cp = ord(ch)
return (
0x4E00 <= cp <= 0x9FFF # CJK Unified Ideographs
or 0x3400 <= cp <= 0x4DBF # CJK Extension A
or 0x3040 <= cp <= 0x30FF # Hiragana / Katakana
or 0xFF00 <= cp <= 0xFFEF # Full-width ASCII & half-width Katakana
or 0xAC00 <= cp <= 0xD7AF # Hangul syllables
)
class ParagraphData:
"""Text and formatting for one paragraph."""
def __init__(self, paragraph: Any):
self.text: str = paragraph.text.strip()
self.bullet: bool = False
self.level: Optional[int] = None
self.alignment: Optional[str] = None
self.space_before: Optional[float] = None
self.space_after: Optional[float] = None
self.font_name: Optional[str] = None
self.font_size: Optional[float] = None
self.bold: Optional[bool] = None
self.italic: Optional[bool] = None
self.underline: Optional[bool] = None
self.color: Optional[str] = None
self.theme_color: Optional[str] = None
self.line_spacing: Optional[float] = None
# Bullet detection
pPr = getattr(getattr(paragraph, "_p", None), "pPr", None)
if pPr is not None and (
pPr.find(f"{_BULLET_NS}buChar") is not None
or pPr.find(f"{_BULLET_NS}buAutoNum") is not None
):
self.bullet = True
self.level = getattr(paragraph, "level", None)
# Alignment (omit LEFT — it's the default)
align = getattr(paragraph, "alignment", None)
if align in _ALIGN_MAP:
self.alignment = _ALIGN_MAP[align]
# Spacing
sb = getattr(paragraph, "space_before", None)
if sb:
self.space_before = sb.pt
sa = getattr(paragraph, "space_after", None)
if sa:
self.space_after = sa.pt
# Font from first run
if paragraph.runs:
font = paragraph.runs[0].font
self.font_name = font.name or None
self.font_size = font.size.pt if font.size else None
self.bold = font.bold
self.italic = font.italic
self.underline = font.underline
try:
self.color = str(font.color.rgb) if font.color.rgb else None
except (AttributeError, TypeError):
try:
tc = font.color.theme_color
self.theme_color = tc.name if tc else None
except (AttributeError, TypeError):
pass
# Line spacing (after font so font_size is available)
ls = getattr(paragraph, "line_spacing", None)
if ls is not None:
if hasattr(ls, "pt"):
self.line_spacing = round(ls.pt, 2)
else:
# Multiplier — convert to points using current font size
self.line_spacing = round(ls * (self.font_size or 12.0), 2)
def to_dict(self) -> Dict[str, Any]:
d: Dict[str, Any] = {"text": self.text}
if self.bullet:
d["bullet"] = True
if self.level is not None:
d["level"] = self.level
if self.alignment:
d["alignment"] = self.alignment
for key in ("space_before", "space_after", "font_size", "line_spacing"):
val = getattr(self, key)
if val is not None:
d[key] = val
if self.font_name:
d["font_name"] = self.font_name
for key in ("bold", "italic", "underline"):
val = getattr(self, key)
if val is not None:
d[key] = val
if self.color:
d["color"] = self.color
elif self.theme_color:
d["theme_color"] = self.theme_color
return d
class ShapeData:
"""Position, formatting metadata, and text content for one shape."""
def __init__(
self,
shape: BaseShape,
absolute_left: Optional[int] = None,
absolute_top: Optional[int] = None,
slide: Optional[Any] = None,
):
self.shape = shape
self.shape_id: str = "" # assigned after sorting
# Slide dimensions (for overflow checking)
self.slide_width_emu: Optional[int] = None
self.slide_height_emu: Optional[int] = None
if slide:
try:
prs_xml = slide.part.package.presentation_part.presentation
self.slide_width_emu = prs_xml.slide_width
self.slide_height_emu = prs_xml.slide_height
except (AttributeError, TypeError):
pass
# Placeholder metadata
self.placeholder_type: Optional[str] = None
self.default_font_size: Optional[float] = None
if getattr(shape, "is_placeholder", False):
pf = shape.placeholder_format # type: ignore
if pf and pf.type:
self.placeholder_type = str(pf.type).split(".")[-1].split(" ")[0]
if slide and hasattr(slide, "slide_layout"):
self.default_font_size = _layout_font_size(shape, slide.slide_layout)
# Position in inches (use absolute coords for shapes inside groups)
left_emu = absolute_left if absolute_left is not None else getattr(shape, "left", 0)
top_emu = absolute_top if absolute_top is not None else getattr(shape, "top", 0)
self.left = round(left_emu / _EMU, 2)
self.top = round(top_emu / _EMU, 2)
self.width = round(getattr(shape, "width", 0) / _EMU, 2)
self.height = round(getattr(shape, "height", 0) / _EMU, 2)
# EMU positions kept for overflow arithmetic
self.left_emu = left_emu
self.top_emu = top_emu
self.width_emu = getattr(shape, "width", 0)
self.height_emu = getattr(shape, "height", 0)
# Issue detection
self.frame_overflow_bottom: Optional[float] = None
self.slide_overflow_right: Optional[float] = None
self.slide_overflow_bottom: Optional[float] = None
self.overlapping_shapes: Dict[str, float] = {}
self.warnings: List[str] = []
self._estimate_frame_overflow()
self._calculate_slide_overflow()
self._detect_bullet_issues()
# ------------------------------------------------------------------
# Issue detection helpers
# ------------------------------------------------------------------
def _default_font_size_pts(self) -> float:
"""Best-effort default font size from theme styles."""
if self.default_font_size:
return self.default_font_size
try:
master = self.shape.part.slide_layout.slide_master # type: ignore
style = "titleStyle" if (self.placeholder_type and "TITLE" in self.placeholder_type) else "bodyStyle"
for child in master.element.iter():
tag = child.tag.split("}")[-1] if "}" in child.tag else child.tag
if tag == style:
for elem in child.iter():
if "sz" in elem.attrib:
return int(elem.attrib["sz"]) / 100.0
except Exception:
pass
return 14.0 # conservative fallback
def _estimate_frame_overflow(self) -> None:
"""Estimate text overflow via character-count heuristic (no external deps)."""
if not hasattr(self.shape, "text_frame"):
return
tf = self.shape.text_frame # type: ignore
if not tf or not tf.paragraphs:
return
# Usable area after text frame margins
def e2i(v: Any) -> float:
return (v or 0) / _EMU
margin_h = e2i(tf.margin_top) + e2i(tf.margin_bottom)
margin_w = e2i(tf.margin_left) + e2i(tf.margin_right)
if margin_h == 0:
margin_h = 0.10 # PowerPoint default: ~0.05" top + 0.05" bottom
if margin_w == 0:
margin_w = 0.20 # PowerPoint default: ~0.1" left + 0.1" right
usable_w = self.width - margin_w
usable_h = self.height - margin_h
if usable_w <= 0 or usable_h <= 0:
return
default_size = self._default_font_size_pts()
total_h = 0.0
for para in tf.paragraphs:
if not para.text.strip():
continue
pd = ParagraphData(para)
size_pt = pd.font_size or default_size
# Estimate text width: CJK chars ≈ 1.0× font_size pts, others ≈ 0.5×
text_w_pts = sum(
size_pt if _is_cjk(c) else size_pt * 0.5
for c in para.text
)
usable_w_pts = usable_w * 72.0
n_lines = max(1, -(-int(text_w_pts) // max(1, int(usable_w_pts)))) # ceiling div
line_h_in = (pd.line_spacing or size_pt) / 72.0
total_h += (pd.space_before or 0) / 72.0
total_h += n_lines * line_h_in
total_h += (pd.space_after or 0) / 72.0
if total_h > usable_h + 0.05: # ignore sub-0.05" rounding noise
self.frame_overflow_bottom = round(total_h - usable_h, 2)
def _calculate_slide_overflow(self) -> None:
if self.slide_width_emu is None or self.slide_height_emu is None:
return
r = self.left_emu + self.width_emu - self.slide_width_emu
if r > 0:
v = round(r / _EMU, 2)
if v > 0.01:
self.slide_overflow_right = v
b = self.top_emu + self.height_emu - self.slide_height_emu
if b > 0:
v = round(b / _EMU, 2)
if v > 0.01:
self.slide_overflow_bottom = v
def _detect_bullet_issues(self) -> None:
if not hasattr(self.shape, "text_frame"):
return
for para in self.shape.text_frame.paragraphs: # type: ignore
text = para.text.strip()
if text and any(text.startswith(s + " ") for s in ("", "", "")):
self.warnings.append("manual_bullet_symbol: use proper bullet formatting")
break
# ------------------------------------------------------------------
# Public interface
# ------------------------------------------------------------------
@property
def paragraphs(self) -> List[ParagraphData]:
if not hasattr(self.shape, "text_frame"):
return []
return [ParagraphData(p) for p in self.shape.text_frame.paragraphs if p.text.strip()] # type: ignore
@property
def has_any_issues(self) -> bool:
return bool(
self.frame_overflow_bottom is not None
or self.slide_overflow_right is not None
or self.slide_overflow_bottom is not None
or self.overlapping_shapes
or self.warnings
)
def to_dict(self) -> Dict[str, Any]:
d: Dict[str, Any] = {
"left": self.left, "top": self.top,
"width": self.width, "height": self.height,
}
if self.placeholder_type:
d["placeholder_type"] = self.placeholder_type
if self.default_font_size:
d["default_font_size"] = self.default_font_size
overflow: Dict[str, Any] = {}
if self.frame_overflow_bottom is not None:
overflow["frame"] = {"overflow_bottom": self.frame_overflow_bottom}
slide_ov: Dict[str, float] = {}
if self.slide_overflow_right is not None:
slide_ov["overflow_right"] = self.slide_overflow_right
if self.slide_overflow_bottom is not None:
slide_ov["overflow_bottom"] = self.slide_overflow_bottom
if slide_ov:
overflow["slide"] = slide_ov
if overflow:
d["overflow"] = overflow
if self.overlapping_shapes:
d["overlap"] = {"overlapping_shapes": self.overlapping_shapes}
if self.warnings:
d["warnings"] = self.warnings
d["paragraphs"] = [p.to_dict() for p in self.paragraphs]
return d
# ------------------------------------------------------------------
# Module-level helpers
# ------------------------------------------------------------------
def _layout_font_size(shape: BaseShape, slide_layout: Any) -> Optional[float]:
"""Extract default font size from the matching layout placeholder."""
try:
shape_type = shape.placeholder_format.type # type: ignore
for ph in slide_layout.placeholders:
if ph.placeholder_format.type == shape_type:
for elem in ph.element.iter():
if "defRPr" in elem.tag and (sz := elem.get("sz")):
return float(sz) / 100.0
break
except Exception:
pass
return None
def _is_valid_shape(shape: BaseShape) -> bool:
"""True if shape has meaningful text and is not a slide-number placeholder."""
if not hasattr(shape, "text_frame"):
return False
tf = shape.text_frame # type: ignore
if not tf or not tf.text.strip():
return False
if getattr(shape, "is_placeholder", False):
pf = shape.placeholder_format # type: ignore
if pf and pf.type:
pt = str(pf.type).split(".")[-1].split(" ")[0]
if pt == "SLIDE_NUMBER":
return False
if pt == "FOOTER" and tf.text.strip().isdigit():
return False
return True
def _collect_shapes(shape: BaseShape, parent_left: int = 0, parent_top: int = 0):
"""Yield (shape, abs_left, abs_top) tuples, recursing into GroupShapes."""
if hasattr(shape, "shapes"): # GroupShape
g_left = parent_left + getattr(shape, "left", 0)
g_top = parent_top + getattr(shape, "top", 0)
for child in shape.shapes: # type: ignore
yield from _collect_shapes(child, g_left, g_top)
elif _is_valid_shape(shape):
yield (
shape,
parent_left + getattr(shape, "left", 0),
parent_top + getattr(shape, "top", 0),
)
def _sort_by_position(shapes: List[ShapeData]) -> List[ShapeData]:
"""Sort shapes top-to-bottom, left-to-right (0.5" row tolerance)."""
if not shapes:
return shapes
shapes = sorted(shapes, key=lambda s: (s.top, s.left))
result: List[ShapeData] = []
row = [shapes[0]]
row_top = shapes[0].top
for s in shapes[1:]:
if abs(s.top - row_top) <= 0.5:
row.append(s)
else:
result.extend(sorted(row, key=lambda s: s.left))
row = [s]
row_top = s.top
result.extend(sorted(row, key=lambda s: s.left))
return result
def _detect_overlaps(shapes: List[ShapeData]) -> None:
"""Populate overlapping_shapes for all pairs with meaningful overlap."""
for i, s1 in enumerate(shapes):
for s2 in shapes[i + 1:]:
ow = min(s1.left + s1.width, s2.left + s2.width) - max(s1.left, s2.left)
oh = min(s1.top + s1.height, s2.top + s2.height) - max(s1.top, s2.top)
if ow > 0.05 and oh > 0.05:
area = round(ow * oh, 2)
s1.overlapping_shapes[s2.shape_id] = area
s2.overlapping_shapes[s1.shape_id] = area
# ------------------------------------------------------------------
# Public API
# ------------------------------------------------------------------
def extract_text_inventory(
pptx_path: Path,
prs: Optional[Any] = None,
issues_only: bool = False,
) -> InventoryData:
"""Extract text from all slides.
Returns {slide-N: {shape-N: ShapeData}}, shapes sorted by visual position.
Pass an existing Presentation object via `prs` to avoid re-loading.
"""
if prs is None:
prs = Presentation(str(pptx_path))
inventory: InventoryData = {}
for slide_idx, slide in enumerate(prs.slides):
raw = list(_collect_shapes_from_slide(slide))
if not raw:
continue
shape_data_list = [ShapeData(s, al, at, slide) for s, al, at in raw]
sorted_shapes = _sort_by_position(shape_data_list)
for idx, sd in enumerate(sorted_shapes):
sd.shape_id = f"shape-{idx}"
if len(sorted_shapes) > 1:
_detect_overlaps(sorted_shapes)
if issues_only:
sorted_shapes = [sd for sd in sorted_shapes if sd.has_any_issues]
if not sorted_shapes:
continue
inventory[f"slide-{slide_idx}"] = {sd.shape_id: sd for sd in sorted_shapes}
return inventory
def _collect_shapes_from_slide(slide):
"""Yield (shape, abs_left, abs_top) for all valid text shapes on a slide."""
for shape in slide.shapes: # type: ignore
yield from _collect_shapes(shape)
def save_inventory(inventory: InventoryData, output_path: Path) -> None:
"""Serialize inventory to a JSON file."""
json_data = {
slide_key: {k: sd.to_dict() for k, sd in shapes.items()}
for slide_key, shapes in inventory.items()
}
with open(output_path, "w", encoding="utf-8") as f:
json.dump(json_data, f, indent=2, ensure_ascii=False)
def main() -> None:
parser = argparse.ArgumentParser(description="Extract text inventory from a PowerPoint file.")
parser.add_argument("input", help="Input .pptx file")
parser.add_argument("output", help="Output .json file")
parser.add_argument("--issues-only", action="store_true",
help="Include only shapes with overflow/overlap issues")
args = parser.parse_args()
input_path = Path(args.input)
if not input_path.exists():
print(f"Error: File not found: {args.input}")
sys.exit(1)
if input_path.suffix.lower() != ".pptx":
print("Error: Input must be a .pptx file")
sys.exit(1)
try:
inventory = extract_text_inventory(input_path, issues_only=args.issues_only)
output_path = Path(args.output)
output_path.parent.mkdir(parents=True, exist_ok=True)
save_inventory(inventory, output_path)
total = sum(len(v) for v in inventory.values())
if args.issues_only:
print(f"Found {total} shapes with issues across {len(inventory)} slides → {args.output}")
else:
print(f"Found {total} text shapes across {len(inventory)} slides → {args.output}")
except Exception as e:
import traceback
print(f"Error: {e}")
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()

2046
skills/ppt/scripts/pdf.py Executable file

File diff suppressed because it is too large Load Diff

144
skills/ppt/scripts/rearrange.py Executable file
View File

@@ -0,0 +1,144 @@
#!/usr/bin/env python3
"""
Rearrange PowerPoint slides based on a sequence of indices.
Usage:
python rearrange.py template.pptx output.pptx 0,34,34,50,52
Slides are 0-indexed. Indices can repeat to duplicate slides.
"""
import argparse
import sys
from copy import deepcopy
from pathlib import Path
from pptx import Presentation
from pptx.oxml.ns import qn
def copy_slide(src_prs: Presentation, dst_prs: Presentation, index: int, dst_layouts: dict) -> None:
"""Append a copy of slide[index] from src_prs into dst_prs."""
src_slide = src_prs.slides[index]
# Match layout by name across all masters; fall back to first available layout
layout_name = src_slide.slide_layout.name
dst_layout = dst_layouts.get(layout_name) or dst_prs.slide_layouts[0]
new_slide = dst_prs.slides.add_slide(dst_layout)
# Clear auto-added placeholder shapes
for shape in list(new_slide.shapes):
sp = shape.element
sp.getparent().remove(sp)
# Copy ALL non-layout relationships from source and build old→new rId mapping.
# This covers images, media, charts, hyperlinks, videos, and any other embedded content.
# Without this, relationship attributes (r:embed, r:id, r:link) in copied shapes would
# reference rIds that don't exist in the new slide, causing PowerPoint repair dialogs.
R_NS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
SKIP_TYPES = {"slideLayout", "notesSlide", "slide"} # handled by python-pptx infrastructure
rId_mapping: dict = {}
for rel_id, rel in src_slide.part.rels.items():
rel_short = rel.reltype.split("/")[-1]
if rel_short in SKIP_TYPES:
continue
new_rId = new_slide.part.rels.get_or_add(rel.reltype, rel._target)
rId_mapping[rel_id] = new_rId
# Copy all shape elements
r_embed = f"{{{R_NS}}}embed"
r_id = f"{{{R_NS}}}id"
r_link = f"{{{R_NS}}}link"
for shape in src_slide.shapes:
new_el = deepcopy(shape.element)
new_slide.shapes._spTree.insert_element_before(new_el, "p:extLst")
# Remap ALL relationship references (images, charts, hyperlinks, video, etc.)
for el in new_el.iter():
for attr in (r_embed, r_id, r_link):
old_rId = el.get(attr)
if old_rId and old_rId in rId_mapping:
el.set(attr, rId_mapping[old_rId])
# Copy slide-level background if defined.
# p:bg lives inside p:cSld, not directly under p:sld.
src_cSld = src_slide.element.find(qn("p:cSld"))
dst_cSld = new_slide.element.find(qn("p:cSld"))
if src_cSld is not None and dst_cSld is not None:
src_bg = src_cSld.find(qn("p:bg"))
if src_bg is not None:
existing_bg = dst_cSld.find(qn("p:bg"))
if existing_bg is not None:
dst_cSld.remove(existing_bg)
dst_cSld.insert(0, deepcopy(src_bg))
def rearrange_presentation(
template_path: Path, output_path: Path, slide_sequence: list[int]
) -> None:
src_prs = Presentation(template_path)
total = len(src_prs.slides)
for idx in slide_sequence:
if idx < 0 or idx >= total:
raise ValueError(f"Slide index {idx} out of range (0{total - 1})")
# Build a fresh presentation with the same dimensions
dst_prs = Presentation(template_path)
# Remove all existing slides from dst_prs
sldIdLst = dst_prs.slides._sldIdLst
for sldId in list(sldIdLst):
rId = sldId.get(qn("r:id")) # must use full namespace via qn(), not bare "r:id"
if rId:
dst_prs.part.drop_rel(rId)
sldIdLst.remove(sldId)
# Search all slide masters for layout matching (templates may have multiple masters)
all_layouts = {
layout.name: layout
for master in dst_prs.slide_masters
for layout in master.slide_layouts
}
# Append slides in requested order (duplicates included)
for idx in slide_sequence:
copy_slide(src_prs, dst_prs, idx, all_layouts)
output_path.parent.mkdir(parents=True, exist_ok=True)
dst_prs.save(output_path)
print(f"Saved {len(slide_sequence)} slides → {output_path}")
def main() -> None:
parser = argparse.ArgumentParser(
description="Rearrange PowerPoint slides.",
epilog="Example: python rearrange.py template.pptx output.pptx 0,34,34,50,52",
)
parser.add_argument("template", help="Path to template PPTX")
parser.add_argument("output", help="Path for output PPTX")
parser.add_argument("sequence", help="Comma-separated 0-based slide indices")
args = parser.parse_args()
template_path = Path(args.template)
if not template_path.exists():
print(f"Error: Template not found: {args.template}")
sys.exit(1)
try:
slide_sequence = [int(x.strip()) for x in args.sequence.split(",")]
except ValueError:
print("Error: sequence must be comma-separated integers (e.g. 0,34,34,50,52)")
sys.exit(1)
try:
rearrange_presentation(template_path, Path(args.output), slide_sequence)
except ValueError as e:
print(f"Error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()

231
skills/ppt/scripts/replace.py Executable file
View File

@@ -0,0 +1,231 @@
#!/usr/bin/env python3
"""Apply text replacements to PowerPoint presentation.
Usage:
python replace.py <input.pptx> <replacements.json> <output.pptx>
The replacements JSON should have the structure output by inventory.py.
ALL text shapes identified by inventory.py will have their text cleared
unless "paragraphs" is specified in the replacements for that shape.
"""
import json
import sys
from pathlib import Path
from typing import Any, Dict, List
from inventory import InventoryData, extract_text_inventory
from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.enum.dml import MSO_THEME_COLOR
from pptx.enum.text import PP_ALIGN
from pptx.oxml.xmlchemy import OxmlElement
from pptx.util import Pt
_ALIGN_MAP = {
"LEFT": PP_ALIGN.LEFT,
"CENTER": PP_ALIGN.CENTER,
"RIGHT": PP_ALIGN.RIGHT,
"JUSTIFY": PP_ALIGN.JUSTIFY,
}
# Bullet indentation constants
# marL = font_size × (1 + level) × 1.6 pts, converted to EMUs (1 pt = 12700 EMU)
_INDENT_FACTOR = 1.6
_EMU_PER_PT = 12700
def _clear_paragraph_bullets(paragraph):
"""Remove all bullet XML elements from a paragraph's pPr."""
pPr = paragraph._element.get_or_add_pPr()
for child in list(pPr):
if any(child.tag.endswith(t) for t in ("buChar", "buNone", "buAutoNum", "buFont")):
pPr.remove(child)
return pPr
def _apply_paragraph_properties(paragraph, para_data: Dict[str, Any]):
text = para_data.get("text", "")
pPr = _clear_paragraph_bullets(paragraph)
if para_data.get("bullet", False):
level = para_data.get("level", 0)
paragraph.level = level
font_size = para_data.get("font_size", 18.0)
pPr.attrib["marL"] = str(int(font_size * _INDENT_FACTOR * (1 + level) * _EMU_PER_PT))
pPr.attrib["indent"] = str(int(-font_size * 0.8 * _EMU_PER_PT))
buChar = OxmlElement("a:buChar")
buChar.set("char", "")
pPr.append(buChar)
if "alignment" not in para_data:
paragraph.alignment = PP_ALIGN.LEFT
else:
pPr.attrib["marL"] = "0"
pPr.attrib["indent"] = "0"
pPr.insert(0, OxmlElement("a:buNone"))
if para_data.get("alignment") in _ALIGN_MAP:
paragraph.alignment = _ALIGN_MAP[para_data["alignment"]]
if "space_before" in para_data:
paragraph.space_before = Pt(para_data["space_before"])
if "space_after" in para_data:
paragraph.space_after = Pt(para_data["space_after"])
if "line_spacing" in para_data:
paragraph.line_spacing = Pt(para_data["line_spacing"])
run = paragraph.runs[0] if paragraph.runs else paragraph.add_run()
run.text = text
_apply_font_properties(run, para_data)
def _apply_font_properties(run, para_data: Dict[str, Any]):
for attr in ("bold", "italic", "underline"):
if attr in para_data:
setattr(run.font, attr, para_data[attr])
if "font_size" in para_data:
run.font.size = Pt(para_data["font_size"])
if "font_name" in para_data:
run.font.name = para_data["font_name"]
if "color" in para_data:
h = para_data["color"].lstrip("#")
if len(h) == 6:
run.font.color.rgb = RGBColor(int(h[0:2], 16), int(h[2:4], 16), int(h[4:6], 16))
elif "theme_color" in para_data:
try:
run.font.color.theme_color = getattr(MSO_THEME_COLOR, para_data["theme_color"])
except AttributeError:
print(f" WARNING: Unknown theme color '{para_data['theme_color']}'")
def _check_duplicate_keys(pairs):
result = {}
for key, value in pairs:
if key in result:
raise ValueError(f"Duplicate key in JSON: '{key}'")
result[key] = value
return result
def _validate_replacements(inventory: InventoryData, replacements: Dict) -> List[str]:
errors = []
for slide_key, shapes_data in replacements.items():
if not slide_key.startswith("slide-"):
continue
if slide_key not in inventory:
errors.append(f"Slide '{slide_key}' not found in inventory")
continue
for shape_key in shapes_data:
if shape_key not in inventory[slide_key]:
available = sorted(inventory[slide_key].keys())
errors.append(
f"Shape '{shape_key}' not found on '{slide_key}'. "
f"Available: {', '.join(available)}"
)
return errors
def apply_replacements(pptx_file: str, json_file: str, output_file: str):
prs = Presentation(pptx_file)
inventory = extract_text_inventory(Path(pptx_file), prs)
# Snapshot original overflow so we can detect if replacements make it worse
original_overflow: Dict[str, Dict[str, float]] = {
slide_key: {
shape_key: sd.frame_overflow_bottom
for shape_key, sd in shapes.items()
if sd.frame_overflow_bottom is not None
}
for slide_key, shapes in inventory.items()
}
with open(json_file) as f:
replacements = json.load(f, object_pairs_hook=_check_duplicate_keys)
errors = _validate_replacements(inventory, replacements)
if errors:
print("ERROR: Invalid shapes in replacement JSON:")
for e in errors:
print(f" - {e}")
raise ValueError(f"Found {len(errors)} validation error(s)")
shapes_cleared = shapes_replaced = 0
for slide_key, shapes_dict in inventory.items():
if not slide_key.startswith("slide-"):
continue
for shape_key, shape_data in shapes_dict.items():
if not shape_data.shape:
continue
tf = shape_data.shape.text_frame # type: ignore
tf.clear()
shapes_cleared += 1
para_list = replacements.get(slide_key, {}).get(shape_key, {}).get("paragraphs")
if not para_list:
continue
shapes_replaced += 1
# Inherit original font_size if not specified in replacement
orig_paras = shape_data.paragraphs or []
orig_font_size = orig_paras[0].get("font_size") if orig_paras else None
for i, para_data in enumerate(para_list):
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
if orig_font_size is not None and "font_size" not in para_data:
para_data = {**para_data, "font_size": orig_font_size}
_apply_paragraph_properties(p, para_data)
# Re-check overflow on the updated in-memory presentation.
# Note: extract_text_inventory may add benign empty <a:solidFill/> elements
# while reading font colors — these are harmless and ignored by PowerPoint.
updated_inventory = extract_text_inventory(Path(pptx_file), prs)
overflow_errors: List[str] = []
warnings: List[str] = []
for slide_key, shapes_dict in updated_inventory.items():
for shape_key, sd in shapes_dict.items():
for w in sd.warnings:
warnings.append(f"{slide_key}/{shape_key}: {w}")
new_ov = sd.frame_overflow_bottom
if new_ov is not None:
old_ov = original_overflow.get(slide_key, {}).get(shape_key, 0.0)
if new_ov > old_ov + 0.01:
overflow_errors.append(
f'{slide_key}/{shape_key}: overflow increased by {new_ov - old_ov:.2f}" '
f'(was {old_ov:.2f}", now {new_ov:.2f}")'
)
if overflow_errors or warnings:
print("\nWARNING: Issues in replacement output:")
for e in overflow_errors:
print(f" overflow - {e}")
for w in warnings:
print(f" warning - {w}")
prs.save(output_file)
print(f"Saved: {output_file}")
print(f" Shapes cleared: {shapes_cleared}, replaced: {shapes_replaced}")
def main():
if len(sys.argv) != 4:
print(__doc__)
sys.exit(1)
input_pptx, replacements_json, output_pptx = (
Path(sys.argv[1]), Path(sys.argv[2]), Path(sys.argv[3])
)
for p in (input_pptx, replacements_json):
if not p.exists():
print(f"Error: File not found: {p}")
sys.exit(1)
try:
apply_replacements(str(input_pptx), str(replacements_json), str(output_pptx))
except Exception as e:
import traceback
print(f"Error: {e}")
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()

BIN
skills/ppt/scripts/tectonic Executable file

Binary file not shown.

352
skills/ppt/scripts/thumbnail.py Executable file
View File

@@ -0,0 +1,352 @@
#!/usr/bin/env python3
"""
Create thumbnail grids from PowerPoint presentation slides.
Creates a grid layout of slide thumbnails with configurable columns (max 6).
Each grid contains up to cols×(cols+1) images. For presentations with more
slides, multiple numbered grid files are created automatically.
The program outputs the names of all files created.
Output:
- Single grid: {prefix}.jpg (if slides fit in one grid)
- Multiple grids: {prefix}-1.jpg, {prefix}-2.jpg, etc.
Grid limits by column count:
- 3 cols: max 12 slides per grid (3×4)
- 4 cols: max 20 slides per grid (4×5)
- 5 cols: max 30 slides per grid (5×6) [default]
- 6 cols: max 42 slides per grid (6×7)
Usage:
python thumbnail.py input.pptx [output_prefix] [--cols N] [--outline-placeholders]
Examples:
python thumbnail.py presentation.pptx
# Creates: thumbnails.jpg (using default prefix)
# Outputs:
# Created 1 grid(s):
# - thumbnails.jpg
python thumbnail.py large-deck.pptx grid --cols 4
# Creates: grid-1.jpg, grid-2.jpg, grid-3.jpg
# Outputs:
# Created 3 grid(s):
# - grid-1.jpg
# - grid-2.jpg
# - grid-3.jpg
python thumbnail.py template.pptx analysis --outline-placeholders
# Creates thumbnail grids with red outlines around text placeholders
"""
import argparse
import subprocess
import sys
import tempfile
from pathlib import Path
from inventory import extract_text_inventory
from PIL import Image, ImageDraw, ImageFont
from pptx import Presentation
# Constants
THUMBNAIL_WIDTH = 300 # Fixed thumbnail width in pixels
CONVERSION_DPI = 100 # DPI for PDF to image conversion
MAX_COLS = 6 # Maximum number of columns
DEFAULT_COLS = 5 # Default number of columns
JPEG_QUALITY = 95 # JPEG compression quality
# Grid layout constants
GRID_PADDING = 20 # Padding between thumbnails
BORDER_WIDTH = 2 # Border width around thumbnails
FONT_SIZE_RATIO = 0.12 # Font size as fraction of thumbnail width
LABEL_PADDING_RATIO = 0.4 # Label padding as fraction of font size
def main():
parser = argparse.ArgumentParser(
description="Create thumbnail grids from PowerPoint slides."
)
parser.add_argument("input", help="Input PowerPoint file (.pptx)")
parser.add_argument(
"output_prefix",
nargs="?",
default="thumbnails",
help="Output prefix for image files (default: thumbnails, will create prefix.jpg or prefix-N.jpg)",
)
parser.add_argument(
"--cols",
type=int,
default=DEFAULT_COLS,
help=f"Number of columns (default: {DEFAULT_COLS}, max: {MAX_COLS})",
)
parser.add_argument(
"--outline-placeholders",
action="store_true",
help="Outline text placeholders with a colored border",
)
args = parser.parse_args()
cols = min(args.cols, MAX_COLS)
if args.cols > MAX_COLS:
print(f"Warning: Columns limited to {MAX_COLS} (requested {args.cols})")
input_path = Path(args.input)
if not input_path.is_file() or input_path.suffix.lower() != ".pptx":
sys.exit(f"Error: Invalid PowerPoint file: {args.input}")
output_path = Path(f"{args.output_prefix}.jpg")
print(f"Processing: {args.input}")
try:
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
placeholder_regions = None
slide_dimensions = None
if args.outline_placeholders:
print("Extracting placeholder regions...")
placeholder_regions, slide_dimensions = get_placeholder_regions(input_path)
if placeholder_regions:
print(f"Found placeholders on {len(placeholder_regions)} slides")
prs = Presentation(str(input_path))
total_slides = len(prs.slides)
hidden_slides = {
idx + 1
for idx, slide in enumerate(prs.slides)
if slide.element.get("show") == "0"
}
hidden_info = f" ({len(hidden_slides)} hidden)" if hidden_slides else ""
print(f"Found {total_slides} slides{hidden_info}")
slide_images = convert_to_images(input_path, temp_path, CONVERSION_DPI, total_slides, hidden_slides)
if not slide_images:
sys.exit("Error: No slides found")
grid_files = create_grids(
slide_images, cols, THUMBNAIL_WIDTH, output_path,
placeholder_regions, slide_dimensions,
)
print(f"Created {len(grid_files)} grid(s):")
for grid_file in grid_files:
print(f" - {grid_file}")
except RuntimeError as e:
sys.exit(f"Error: {e}")
def create_hidden_slide_placeholder(size):
"""Create placeholder image for hidden slides."""
img = Image.new("RGB", size, color="#F0F0F0")
draw = ImageDraw.Draw(img)
line_width = max(5, min(size) // 100)
draw.line([(0, 0), size], fill="#CCCCCC", width=line_width)
draw.line([(size[0], 0), (0, size[1])], fill="#CCCCCC", width=line_width)
return img
def get_placeholder_regions(pptx_path):
"""Extract ALL text regions from the presentation.
Returns a tuple of (placeholder_regions, slide_dimensions).
text_regions is a dict mapping slide indices to lists of text regions.
Each region is a dict with 'left', 'top', 'width', 'height' in inches.
slide_dimensions is a tuple of (width_inches, height_inches).
"""
prs = Presentation(str(pptx_path))
inventory = extract_text_inventory(pptx_path, prs)
placeholder_regions = {}
slide_width_inches = (prs.slide_width or 9144000) / 914400.0
slide_height_inches = (prs.slide_height or 5143500) / 914400.0
for slide_key, shapes in inventory.items():
slide_idx = int(slide_key.split("-")[1])
regions = [
{"left": s.left, "top": s.top, "width": s.width, "height": s.height}
for s in shapes.values()
]
if regions:
placeholder_regions[slide_idx] = regions
return placeholder_regions, (slide_width_inches, slide_height_inches)
def _pptx_to_pdf(pptx_path, temp_dir):
"""Convert PPTX to PDF via LibreOffice. Returns path to the PDF file."""
pdf_path = temp_dir / f"{pptx_path.stem}.pdf"
result = subprocess.run(
["soffice", "--headless", "--convert-to", "pdf", "--outdir", str(temp_dir), str(pptx_path)],
capture_output=True,
text=True,
)
if result.returncode != 0 or not pdf_path.exists():
raise RuntimeError("PDF conversion failed")
return pdf_path
def _pdf_to_images(pdf_path, temp_dir, dpi):
"""Convert PDF pages to JPEG images via pdftoppm. Returns sorted image paths."""
result = subprocess.run(
["pdftoppm", "-jpeg", "-r", str(dpi), str(pdf_path), str(temp_dir / "slide")],
capture_output=True,
text=True,
)
if result.returncode != 0:
raise RuntimeError("Image conversion failed")
return sorted(temp_dir.glob("slide-*.jpg"))
def convert_to_images(pptx_path, temp_dir, dpi, total_slides, hidden_slides):
"""Convert PowerPoint to images via PDF, inserting placeholders for hidden slides."""
pdf_path = _pptx_to_pdf(pptx_path, temp_dir)
visible_images = _pdf_to_images(pdf_path, temp_dir, dpi)
if not visible_images:
return []
with Image.open(visible_images[0]) as img:
placeholder_size = img.size
all_images = []
visible_idx = 0
for slide_num in range(1, total_slides + 1):
if slide_num in hidden_slides:
placeholder_path = temp_dir / f"hidden-{slide_num:03d}.jpg"
create_hidden_slide_placeholder(placeholder_size).save(placeholder_path, "JPEG")
all_images.append(placeholder_path)
else:
if visible_idx < len(visible_images):
all_images.append(visible_images[visible_idx])
visible_idx += 1
return all_images
def create_grids(
image_paths,
cols,
width,
output_path,
placeholder_regions=None,
slide_dimensions=None,
):
"""Create multiple thumbnail grids from slide images, max cols×(cols+1) images per grid."""
max_images_per_grid = cols * (cols + 1)
grid_files = []
total_images = len(image_paths)
for chunk_idx, start_idx in enumerate(range(0, total_images, max_images_per_grid)):
chunk_images = image_paths[start_idx: start_idx + max_images_per_grid]
grid = create_grid(chunk_images, cols, width, start_idx, placeholder_regions, slide_dimensions)
if total_images <= max_images_per_grid:
grid_filename = output_path
else:
grid_filename = output_path.parent / f"{output_path.stem}-{chunk_idx + 1}{output_path.suffix}"
grid_filename.parent.mkdir(parents=True, exist_ok=True)
grid.save(str(grid_filename), quality=JPEG_QUALITY)
grid_files.append(str(grid_filename))
return grid_files
def create_grid(
image_paths,
cols,
width,
start_slide_num=0,
placeholder_regions=None,
slide_dimensions=None,
):
"""Create thumbnail grid from slide images with optional placeholder outlining."""
font_size = int(width * FONT_SIZE_RATIO)
label_padding = int(font_size * LABEL_PADDING_RATIO)
with Image.open(image_paths[0]) as img:
aspect = img.height / img.width
height = int(width * aspect)
rows = (len(image_paths) + cols - 1) // cols
grid_w = cols * width + (cols + 1) * GRID_PADDING
grid_h = rows * (height + font_size + label_padding * 2) + (rows + 1) * GRID_PADDING
grid = Image.new("RGB", (grid_w, grid_h), "white")
draw = ImageDraw.Draw(grid)
try:
font = ImageFont.load_default(size=font_size)
except Exception:
font = ImageFont.load_default()
for i, img_path in enumerate(image_paths):
row, col = i // cols, i % cols
x = col * width + (col + 1) * GRID_PADDING
y_base = row * (height + font_size + label_padding * 2) + (row + 1) * GRID_PADDING
label = f"{start_slide_num + i}"
bbox = draw.textbbox((0, 0), label, font=font)
text_w = bbox[2] - bbox[0]
draw.text((x + (width - text_w) // 2, y_base + label_padding), label, fill="black", font=font)
y_thumbnail = y_base + label_padding + font_size + label_padding
with Image.open(img_path) as img:
orig_w, orig_h = img.size
if placeholder_regions and (start_slide_num + i) in placeholder_regions:
if img.mode != "RGBA":
img = img.convert("RGBA")
regions = placeholder_regions[start_slide_num + i]
if slide_dimensions:
slide_w_in, slide_h_in = slide_dimensions
else:
slide_w_in = orig_w / CONVERSION_DPI
slide_h_in = orig_h / CONVERSION_DPI
x_scale = orig_w / slide_w_in
y_scale = orig_h / slide_h_in
overlay = Image.new("RGBA", img.size, (255, 255, 255, 0))
overlay_draw = ImageDraw.Draw(overlay)
stroke_width = max(5, min(orig_w, orig_h) // 150)
for region in regions:
px_left = int(region["left"] * x_scale)
px_top = int(region["top"] * y_scale)
px_right = px_left + int(region["width"] * x_scale)
px_bottom = px_top + int(region["height"] * y_scale)
overlay_draw.rectangle(
[(px_left, px_top), (px_right, px_bottom)],
outline=(255, 0, 0, 255),
width=stroke_width,
)
img = Image.alpha_composite(img, overlay).convert("RGB")
img.thumbnail((width, height), Image.Resampling.LANCZOS)
w, h = img.size
tx = x + (width - w) // 2
ty = y_thumbnail + (height - h) // 2
grid.paste(img, (tx, ty))
if BORDER_WIDTH > 0:
draw.rectangle(
[(tx - BORDER_WIDTH, ty - BORDER_WIDTH), (tx + w + BORDER_WIDTH - 1, ty + h + BORDER_WIDTH - 1)],
outline="gray",
width=BORDER_WIDTH,
)
return grid
if __name__ == "__main__":
main()

197
skills/ppt/setup.sh Executable file
View File

@@ -0,0 +1,197 @@
#!/usr/bin/env bash
# ---
# name: ppt-setup
# author: Z.AI
# version: "1.0"
# description: Environment setup for the PPT skill. Checks and installs all required dependencies.
# ---
#
# Installs only dependencies required by the PPT skill.
set -euo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
ok() { echo -e " ${GREEN}${NC} $1"; }
fail() { echo -e " ${RED}${NC} $1"; }
warn() { echo -e " ${YELLOW}${NC} $1"; }
info() { echo -e " ${BLUE}${NC} $1"; }
echo "============================================"
echo " PPT Skill — Environment Setup"
echo "============================================"
echo ""
OS="$(uname -s)"
ARCH="$(uname -m)"
echo "Platform: $OS $ARCH"
echo ""
# ── 0. macOS: Homebrew ──
if [ "$OS" = "Darwin" ]; then
echo "--- Homebrew (macOS package manager) ---"
if command -v brew &>/dev/null; then
BREW_VER=$(brew --version 2>/dev/null | head -1)
ok "brew ($BREW_VER)"
else
fail "brew not found — Node.js install needs Homebrew on macOS"
info "Install: /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
fi
echo ""
fi
# ── 1. Node.js (PptxGenJS runs on Node) ──
echo "--- Node.js ---"
if command -v node &>/dev/null; then
NODE_VER=$(node --version)
ok "node ($NODE_VER)"
else
fail "node not found (required — PPTX generation uses PptxGenJS on Node)"
case "$OS" in
Darwin) info "Install: brew install node" ;;
Linux) info "Install: curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -"
info " sudo apt install -y nodejs" ;;
*) info "Install: https://nodejs.org/" ;;
esac
fi
# ── 2. npm ──
echo ""
echo "--- npm ---"
if command -v npm &>/dev/null; then
NPM_VER=$(npm --version 2>/dev/null)
ok "npm ($NPM_VER)"
else
fail "npm not found"
case "$OS" in
Darwin) info "Install: brew install node (includes npm)" ;;
Linux) info "Install: comes with nodejs" ;;
*) info "Install: https://nodejs.org/" ;;
esac
fi
# ── 3. npm package: pptxgenjs ──
echo ""
echo "--- npm Packages ---"
if node -e "require('pptxgenjs')" 2>/dev/null || npm list -g pptxgenjs &>/dev/null; then
PPTX_VER=$(node -e "try{console.log(require('pptxgenjs/package.json').version)}catch(e){console.log('installed')}" 2>/dev/null)
ok "pptxgenjs ($PPTX_VER)"
else
fail "pptxgenjs not installed"
info "Install: npm install -g pptxgenjs"
echo ""
if [ -t 0 ]; then
read -p " Install now? [Y/n] " -n 1 -r REPLY
echo ""
REPLY=${REPLY:-Y}
else
warn "Non-interactive mode — skipping auto-install."
REPLY=N
fi
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
npm install -g pptxgenjs 2>/dev/null && ok "Installed: pptxgenjs" || fail "npm install failed"
fi
fi
# ── 4. Python 3 (OOXML validation scripts) ──
echo ""
echo "--- Python (OOXML validation) ---"
if command -v python3 &>/dev/null; then
PY_VER=$(python3 --version 2>&1)
ok "python3 ($PY_VER)"
if [ "$OS" = "Darwin" ]; then
PY_PATH=$(which python3 2>/dev/null)
if [[ "$PY_PATH" == "/usr/bin/python3" ]]; then
warn "Using macOS system Python (limited). Recommend: brew install python3"
fi
fi
else
fail "python3 not found"
case "$OS" in
Darwin) info "Install: brew install python3" ;;
Linux) info "Install: sudo apt install python3 python3-pip (Debian/Ubuntu)"
info " sudo dnf install python3 python3-pip (Fedora/RHEL)" ;;
*) info "Install: https://www.python.org/downloads/" ;;
esac
fi
# ── 5. pip ──
echo ""
echo "--- pip ---"
if python3 -m pip --version &>/dev/null 2>&1; then
PIP_VER=$(python3 -m pip --version 2>/dev/null | head -1)
ok "pip ($PIP_VER)"
else
fail "pip not found"
case "$OS" in
Darwin) info "Install: python3 -m ensurepip --upgrade"
info " or: brew install python3 (includes pip)" ;;
Linux) info "Install: sudo apt install python3-pip (Debian/Ubuntu)" ;;
*) info "Install: python3 -m ensurepip --upgrade" ;;
esac
fi
# ── 6. Python packages ──
echo ""
echo "--- Python Packages ---"
PY_PKGS=(
"lxml:lxml"
"defusedxml:defusedxml"
)
MISSING_PY=()
for entry in "${PY_PKGS[@]}"; do
mod="${entry%%:*}"
pkg="${entry##*:}"
if python3 -c "import $mod" 2>/dev/null; then
ver=$(python3 -c "import $mod; print(getattr($mod, '__version__', 'installed'))" 2>/dev/null)
ok "$pkg ($ver)"
else
fail "$pkg not installed"
MISSING_PY+=("$pkg")
fi
done
if [ ${#MISSING_PY[@]} -gt 0 ]; then
echo ""
if [ -t 0 ]; then
read -p " Install missing Python packages? [Y/n] " -n 1 -r REPLY
echo ""
REPLY=${REPLY:-Y}
else
warn "Non-interactive mode — skipping auto-install. Run interactively or install manually."
REPLY=N
fi
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
python3 -m pip install -q "${MISSING_PY[@]}" 2>/dev/null \
|| python3 -m pip install -q --user "${MISSING_PY[@]}" 2>/dev/null \
|| python3 -m pip install -q --break-system-packages "${MISSING_PY[@]}" 2>/dev/null \
|| { fail "pip install failed. Try manually: pip install ${MISSING_PY[*]}"; }
ok "Installed: ${MISSING_PY[*]}"
fi
fi
# ── 7. Tectonic (optional, for Beamer/LaTeX slides) ──
echo ""
echo "--- Tectonic (optional, Beamer slides only) ---"
if command -v tectonic &>/dev/null; then
TEC_VER=$(tectonic --version 2>&1 | head -1)
ok "tectonic ($TEC_VER)"
elif [ -x "$HOME/tectonic" ]; then
ok "tectonic (~/tectonic)"
else
warn "tectonic not installed (needed only for Beamer/LaTeX slide PDFs)"
case "$OS" in
Darwin) info "Install: brew install tectonic" ;;
Linux) info "Install: conda install -c conda-forge tectonic"
info " or: curl -fsSL https://drop-sh.fullyjustified.net | sh" ;;
MINGW*|MSYS*|CYGWIN*) info "Install: scoop install tectonic" ;;
esac
fi
# ── Summary ──
echo ""
echo "============================================"
echo " Setup complete."
echo " Core: Node.js + pptxgenjs"
echo " Validation: Python + lxml + defusedxml"
echo " Beamer slides: tectonic (optional)"
echo "============================================"

581
skills/ppt/themes.md Executable file
View File

@@ -0,0 +1,581 @@
# Themes — Preset Theme Configuration
Each theme = a set of colors + a set of fonts + mood tags. Once a theme is selected, all colors are automatically derived according to the color scale rules in `design-system.md`.
---
## Theme Selection Rules
1. AI selects the theme based on scene classification and content tone
2. Each PPT deck uses only one theme, **no switching throughout**
3. If the user specifies a color or style preference, select the closest theme or customize accordingly (still must follow color scale rules)
---
## Preset Themes
### 1. Ocean (Deep Sea Blue)
| Property | Value |
|------|-----|
| **Mood** | Professional, trustworthy |
| **Suitable for** | Work reports, business proposals, company introductions |
| **Primary** | `#1B2A4A` |
| **Accent (A — default)** | `#2A9D8F` (teal) |
| **Accent B** | `#D7A460` (warm gold) |
| **Accent C** | `#6C92E0` (bright blue) |
| **CJK Title Font** | Microsoft YaHei Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Gill Sans MT Bold |
| **Latin Body Font** | Gill Sans MT |
| **Image Keywords** | ocean, deep blue, corporate, skyline, technology, water, aerial city |
| **Mask Color** | `rgba(18,32,64,0.75)` (primary-90 based) |
Color Scale:
| Scale | Color Value | Usage Example |
|------|------|---------|
| primary-100 | `#0D1525` | Dark mode background |
| primary-90 | `#122040` | Title bar background |
| primary-80 | `#1B2A4A` | Title text |
| primary-60 | `#3D5A80` | Subtitle / icons |
| primary-40 | `#6B8AB0` | Secondary text |
| primary-20 | `#B0C4DE` | Light decoration |
| primary-10 | `#DFE8F2` | Card background / border |
| primary-5 | `#F0F4F8` | Surface base color |
---
### 2. Graphite (Graphite Gray)
| Property | Value |
|------|-----|
| **Mood** | Modern, restrained, clean and sharp |
| **Suitable for** | Tech products, weekly/monthly reports, technical sharing |
| **Primary** | `#2D3436` |
| **Accent (A — default)** | `#D77860` (coral red) |
| **Accent B** | `#6BCB77` (emerald green) |
| **Accent C** | `#9B8EC4` (light purple) |
| **CJK Title Font** | SimHei Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Century Gothic Bold |
| **Latin Body Font** | Corbel |
| **Image Keywords** | architecture, minimal, concrete, technology, geometric, monochrome, server room |
| **Mask Color** | `rgba(34,40,41,0.75)` (primary-90 based) |
Color Scale:
| Scale | Color Value |
|------|------|
| primary-100 | `#161A1B` |
| primary-90 | `#222829` |
| primary-80 | `#2D3436` |
| primary-60 | `#576163` |
| primary-40 | `#8D9496` |
| primary-20 | `#C3C8CA` |
| primary-10 | `#E4E7E8` |
| primary-5 | `#F3F4F5` |
---
### 3. Forest (Forest Green)
| Property | Value |
|------|-----|
| **Mood** | Natural, serene, organic and gentle |
| **Suitable for** | Educational courseware, humanities/liberal arts academic, ESG/sustainability |
| **Primary** | `#1B4332` |
| **Accent (A — default)** | `#DCBD74` (golden) |
| **Accent B** | `#E18C70` (coral) |
| **Accent C** | `#7EC8B0` (mint) |
| **CJK Title Font** | SimSun Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Palatino Linotype Bold |
| **Latin Body Font** | Corbel |
| **Image Keywords** | forest, nature, leaves, green, organic, sustainability, botanical, meadow |
| **Mask Color** | `rgba(18,45,31,0.75)` (primary-90 based) |
Color Scale:
| Scale | Color Value |
|------|------|
| primary-100 | `#0B1E14` |
| primary-90 | `#122D1F` |
| primary-80 | `#1B4332` |
| primary-60 | `#2E6B4F` |
| primary-40 | `#60A882` |
| primary-20 | `#A8D4BC` |
| primary-10 | `#D8EEE2` |
| primary-5 | `#EEF7F1` |
---
### 4. Twilight (Dark Night Purple)
| Property | Value |
|------|-----|
| **Mood** | Creative, unique, personality-driven |
| **Suitable for** | Creative proposals, brand planning, design sharing |
| **Primary** | `#2D2B55` |
| **Accent (A — default)** | `#9B50F5` (electric purple) |
| **Accent B** | `#E3B27D` (warm orange) |
| **Accent C** | `#5EC4D4` (sky blue) |
| **CJK Title Font** | Microsoft YaHei Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Candara Bold |
| **Latin Body Font** | Candara |
| **Image Keywords** | galaxy, night sky, aurora, creative, neon, abstract art, purple gradient |
| **Mask Color** | `rgba(33,31,64,0.75)` (primary-90 based) |
Color Scale:
| Scale | Color Value |
|------|------|
| primary-100 | `#15142A` |
| primary-90 | `#211F40` |
| primary-80 | `#2D2B55` |
| primary-60 | `#555380` |
| primary-40 | `#8886AB` |
| primary-20 | `#BFBED6` |
| primary-10 | `#E2E1ED` |
| primary-5 | `#F2F2F7` |
---
### 5. Sandstone (Warm Sand)
| Property | Value |
|------|-----|
| **Mood** | Premium, warm, composed and grand |
| **Suitable for** | Investment roadshows, real estate, luxury goods, finance |
| **Primary** | `#3C2415` |
| **Accent (A — default)** | `#C09E30` (gold) |
| **Accent B** | `#D4766A` (ochre red) |
| **Accent C** | `#8BB174` (olive) |
| **CJK Title Font** | SimSun Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Palatino Linotype Bold |
| **Latin Body Font** | Corbel |
| **Image Keywords** | luxury, gold, marble, architecture, warm light, classical, elegant interior |
| **Mask Color** | `rgba(45,27,16,0.75)` (primary-90 based) |
Color Scale:
| Scale | Color Value |
|------|------|
| primary-100 | `#1E120A` |
| primary-90 | `#2D1B10` |
| primary-80 | `#3C2415` |
| primary-60 | `#6B5443` |
| primary-40 | `#9E8A7A` |
| primary-20 | `#CEBFB5` |
| primary-10 | `#E9E2DC` |
| primary-5 | `#F5F2F0` |
---
### 6. Mono (Minimalist Black)
| Property | Value |
|------|-----|
| **Mood** | Sharp, minimalist, visual impact |
| **Suitable for** | Product launches, minimalist style, photography showcases |
| **Primary** | `#1A1A1A` |
| **Accent (A — default)** | `#E6754C` (burnt orange) |
| **Accent B** | `#4ECDC4` (cyan) |
| **Accent C** | `#C44569` (rose) |
| **CJK Title Font** | Microsoft YaHei Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Arial Bold |
| **Latin Body Font** | Arial |
| **Image Keywords** | minimal, black white, contrast, product, clean, abstract, studio lighting |
| **Mask Color** | `rgba(20,20,20,0.75)` (primary-90 based) |
Color Scale:
| Scale | Color Value |
|------|------|
| primary-100 | `#0A0A0A` |
| primary-90 | `#141414` |
| primary-80 | `#1A1A1A` |
| primary-60 | `#4A4A4A` |
| primary-40 | `#808080` |
| primary-20 | `#B8B8B8` |
| primary-10 | `#E0E0E0` |
| primary-5 | `#F2F2F2` |
---
### 7. Deep Mineral (Dark Night Blue)
| Property | Value |
|------|-----|
| **Mood** | High-end, immersive, cinematic depth |
| **Suitable for** | Tech launches, keynotes, data dashboards, night-mode presentations |
| **Primary** | `#FFFFFF` |
| **Accent (A — default)** | `#44D1E4` (electric cyan) |
| **Accent B** | `#EDCD82` (warm yellow) |
| **Accent C** | `#E65174` (rose) |
| **Background Override** | `#162235` (replaces default `#FFFFFF`) |
| **CJK Title Font** | Microsoft YaHei Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Trebuchet MS Bold |
| **Latin Body Font** | Corbel |
| **Image Keywords** | dark blue, night city, deep ocean, space, data visualization, neon glow |
| **Mask Color** | `rgba(16,26,40,0.70)` (primary-100 based) |
**Dark theme notes**: This is a dark-background theme — the color logic is inverted:
- `background` = `#162235` (dark), `surface` = `#1E2D45` (slightly lighter), `surface-card` = `#243550` (card layer)
- `text-primary` = `#FFFFFF`, `text-secondary` = `rgba(255,255,255,0.75)`, `text-muted` = `rgba(255,255,255,0.45)`
- Cards use `surface-card` with no shadow (shadows invisible on dark backgrounds)
- Accent (`#44D1E4`) is used for highlights, KPI numbers, accent bars, and emphasis elements
Color Scale (inverted — lighter values are "darker" in visual weight):
| Scale | Color Value | Usage |
|------|------|---------|
| primary-100 | `#0D1525` | Deepest background |
| primary-90 | `#122040` | Title bar background |
| primary-80 | `#FFFFFF` | Title text / primary elements |
| primary-60 | `rgba(255,255,255,0.75)` | Subtitle / secondary text |
| primary-40 | `rgba(255,255,255,0.45)` | Muted text / annotations |
| primary-20 | `#2A3F5F` | Card borders / subtle decorations |
| primary-10 | `#1E2D45` | Surface / content area base |
| primary-5 | `#162235` | Page background |
---
### 8. Warm Retro (Vintage Warmth)
| Property | Value |
|------|-----|
| **Mood** | Vintage, cultured, warm and grounded |
| **Suitable for** | Cultural events, humanities, food/lifestyle, brand storytelling |
| **Primary** | `#2A4A3A` |
| **Accent (A — default)** | `#C89F62` (antique gold) |
| **Accent B** | `#C06C58` (copper red) |
| **Accent C** | `#7BA68C` (moss green) |
| **Background Override** | `#F4F1E9` (warm off-white, replaces default `#FFFFFF`) |
| **CJK Title Font** | SimSun Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Palatino Linotype Bold |
| **Latin Body Font** | Garamond |
| **Image Keywords** | vintage, warm light, craft, leather, coffee, botanical, old book, linen texture |
| **Mask Color** | `rgba(30,40,34,0.75)` (primary-90 based) |
**Warm background notes**: This theme uses a warm off-white (`#F4F1E9`) instead of pure white:
- `background` = `#F4F1E9`, `surface` = `#EDE9DF` (slightly darker warm), `surface-card` = `#FEFDFB` (near-white card)
- The warm base gives a cozy, analog feel — avoid pure white elements that would look jarring
Color Scale:
| Scale | Color Value | Usage |
|------|------|---------|
| primary-100 | `#0F1C15` | Darkest (rarely used) |
| primary-90 | `#1E2822` | Title bar background |
| primary-80 | `#2A4A3A` | Title text / primary elements |
| primary-60 | `#4A7A62` | Subtitle / icons |
| primary-40 | `#7AAA90` | Secondary text |
| primary-20 | `#B5D4C2` | Light decoration |
| primary-10 | `#DCE9E0` | Card background / border |
| primary-5 | `#F0F5F1` | Surface base (use `#EDE9DF` for warm surface) |
---
### 9. Deep Forest (Dark Green)
| Property | Value |
|------|-----|
| **Mood** | Calm, grounded, nature-tech fusion |
| **Suitable for** | ESG reports, sustainability, ecology, green tech |
| **Primary** | `#FFFFFF` |
| **Accent (A — default)** | `#D7D968` (electric lime) |
| **Accent B** | `#E18C70` (coral orange) |
| **Accent C** | `#85C5E0` (sky blue) |
| **Background Override** | `#193328` (deep forest green, replaces default `#FFFFFF`) |
| **CJK Title Font** | Microsoft YaHei Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Gill Sans MT Bold |
| **Latin Body Font** | Corbel |
| **Image Keywords** | dark forest, moss, fern, green nature, sustainability, eco technology, rain forest |
| **Mask Color** | `rgba(18,38,30,0.70)` (primary-100 based) |
**Dark theme notes**: Same inverted logic as Deep Mineral — see its notes above.
- `background` = `#193328`, `surface` = `#1F3F32`, `surface-card` = `#264A3C`
- `text-primary` = `#FFFFFF`, `text-secondary` = `rgba(255,255,255,0.75)`, `text-muted` = `rgba(255,255,255,0.45)`
Color Scale (inverted):
| Scale | Color Value | Usage |
|------|------|---------|
| primary-100 | `#0D1A14` | Deepest background |
| primary-90 | `#12261E` | Title bar background |
| primary-80 | `#FFFFFF` | Title text / primary elements |
| primary-60 | `rgba(255,255,255,0.75)` | Subtitle / secondary text |
| primary-40 | `rgba(255,255,255,0.45)` | Muted text / annotations |
| primary-20 | `#2A5040` | Card borders / subtle decorations |
| primary-10 | `#1F3F32` | Surface / content area base |
| primary-5 | `#193328` | Page background |
---
### 10. Coral (Coral Pink)
| Property | Value |
|------|-----|
| **Mood** | Warm, vibrant, youthful |
| **Suitable for** | Brand marketing, consumer products, lifestyle, female-audience presentations |
| **Primary** | `#8B3A4A` |
| **Accent (A — default)** | `#E2A574` (warm peach) |
| **Accent B** | `#DC755B` (burnt sienna) |
| **Accent C** | `#6BC5B8` (mint contrast) |
| **CJK Title Font** | Microsoft YaHei Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Candara Bold |
| **Latin Body Font** | Corbel |
| **Image Keywords** | pink, flowers, beauty, lifestyle, warm light, cafe, fashion, soft texture |
| **Mask Color** | `rgba(100,42,54,0.75)` (primary-90 based) |
Color Scale:
| Scale | Color Value | Usage |
|------|------|---------|
| primary-100 | `#3D1A22` | Deepest background |
| primary-90 | `#642A36` | Title bar background |
| primary-80 | `#8B3A4A` | Title text / primary elements |
| primary-60 | `#B06070` | Subtitle / icons |
| primary-40 | `#D08A96` | Secondary text |
| primary-20 | `#E8BAC2` | Light decoration |
| primary-10 | `#F3DDE1` | Card background / border |
| primary-5 | `#FAF0F2` | Surface base color |
---
### 11. Mint (Mint Green)
| Property | Value |
|------|-----|
| **Mood** | Fresh, clean, health-oriented |
| **Suitable for** | Healthcare, wellness, eco-friendly, food & beverage |
| **Primary** | `#1A6B5A` |
| **Accent (A — default)** | `#E3987D` (warm coral) |
| **Accent B** | `#DEC363` (golden yellow) |
| **Accent C** | `#8574E2` (medium slate blue) |
| **CJK Title Font** | Microsoft YaHei Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Gill Sans MT Bold |
| **Latin Body Font** | Corbel |
| **Image Keywords** | mint, fresh, health, botanical, clean, green smoothie, spa, herbal |
| **Mask Color** | `rgba(18,78,64,0.75)` (primary-90 based) |
Color Scale:
| Scale | Color Value | Usage |
|------|------|---------|
| primary-100 | `#0A3028` | Deepest background |
| primary-90 | `#124E40` | Title bar background |
| primary-80 | `#1A6B5A` | Title text / primary elements |
| primary-60 | `#3D9B86` | Subtitle / icons |
| primary-40 | `#6DBFAB` | Secondary text |
| primary-20 | `#A8DACE` | Light decoration |
| primary-10 | `#D6EDE7` | Card background / border |
| primary-5 | `#EFF8F5` | Surface base color |
---
### 12. Azure (Sky Blue)
| Property | Value |
|------|-----|
| **Mood** | Open, lightweight, approachable technology |
| **Suitable for** | SaaS products, AI/tech, onboarding, training materials |
| **Primary** | `#1E5F8C` |
| **Accent (A — default)** | `#FF6B2B` (electric orange) |
| **Accent B** | `#DD5F5F` (red) |
| **Accent C** | `#9270E1` (violet) |
| **CJK Title Font** | Microsoft YaHei Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Trebuchet MS Bold |
| **Latin Body Font** | Corbel |
| **Image Keywords** | sky, cloud, technology, light blue, software, digital, clean interface |
| **Mask Color** | `rgba(20,68,104,0.75)` (primary-90 based) |
Color Scale:
| Scale | Color Value | Usage |
|------|------|---------|
| primary-100 | `#0C2A40` | Deepest background |
| primary-90 | `#144468` | Title bar background |
| primary-80 | `#1E5F8C` | Title text / primary elements |
| primary-60 | `#4085B0` | Subtitle / icons |
| primary-40 | `#70AAD0` | Secondary text |
| primary-20 | `#A8CEE5` | Light decoration |
| primary-10 | `#D8E9F3` | Card background / border |
| primary-5 | `#F0F6FA` | Surface base color |
---
### 13. Ember (Amber Red)
| Property | Value |
|------|-----|
| **Mood** | Bold, energetic, high-impact |
| **Suitable for** | Annual events, product launches, sales campaigns, motivational presentations |
| **Primary** | `#8B2500` |
| **Accent (A — default)** | `#F04828` (fire orange) |
| **Accent B** | `#2EC4B6` (teal contrast) |
| **Accent C** | `#EC7979` (coral red) |
| **CJK Title Font** | SimHei Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Arial Bold |
| **Latin Body Font** | Corbel |
| **Image Keywords** | fire, red, energy, stage light, celebration, bold, dynamic, explosion |
| **Mask Color** | `rgba(100,26,0,0.75)` (primary-90 based) |
Color Scale:
| Scale | Color Value | Usage |
|------|------|---------|
| primary-100 | `#3E1000` | Deepest background |
| primary-90 | `#641A00` | Title bar background |
| primary-80 | `#8B2500` | Title text / primary elements |
| primary-60 | `#B85030` | Subtitle / icons |
| primary-40 | `#D88060` | Secondary text |
| primary-20 | `#EBB8A0` | Light decoration |
| primary-10 | `#F5DCD0` | Card background / border |
| primary-5 | `#FBF0EB` | Surface base color |
---
### 14. Volt (Electric / Startup Dark)
| Property | Value |
|------|-----|
| **Mood** | Electric, aggressive, high-energy |
| **Suitable for** | AI/tech product launches, startup pitches, youth tech brands, digital innovation |
| **Primary** | `#FFFFFF` |
| **Accent (A — default)** | `#00F5A0` (electric mint-green) |
| **Accent B** | `#FF5E3A` (electric orange) |
| **Accent C** | `#A855F7` (electric purple) |
| **Background Override** | `#080B14` (near-black with blue tint, replaces default `#FFFFFF`) |
| **CJK Title Font** | Microsoft YaHei Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Trebuchet MS Bold |
| **Latin Body Font** | Corbel |
| **Image Keywords** | neon, circuit board, futuristic, dark ui, electric glow, startup, code, data stream |
| **Mask Color** | `rgba(5,7,16,0.70)` (primary-100 based) |
**Dark theme notes**: Same inverted logic as Deep Mineral — see its notes above.
- `background` = `#080B14`, `surface` = `#0F1424`, `surface-card` = `#162033`
- `text-primary` = `#FFFFFF`, `text-secondary` = `rgba(255,255,255,0.75)`, `text-muted` = `rgba(255,255,255,0.45)`
- Accents are extremely vivid by design — use sparingly (bars, numbers, key labels only)
Color Scale (inverted):
| Scale | Color Value | Usage |
|------|------|---------|
| primary-100 | `#050710` | Deepest background |
| primary-90 | `#0D1320` | Title bar background |
| primary-80 | `#FFFFFF` | Title text / primary elements |
| primary-60 | `rgba(255,255,255,0.75)` | Subtitle / secondary text |
| primary-40 | `rgba(255,255,255,0.45)` | Muted text / annotations |
| primary-20 | `#1E2E48` | Card borders / subtle decorations |
| primary-10 | `#0F1424` | Surface / content area base |
| primary-5 | `#080B14` | Page background |
---
### 15. Vermillion (Chinese Red)
| Property | Value |
|------|-----|
| **Mood** | Ceremonial, festive, culturally resonant |
| **Suitable for** | Chinese cultural events, Spring Festival, traditional ceremonies, brand storytelling with Chinese aesthetics |
| **Primary** | `#8B1A1A` |
| **Accent (A — default)** | `#D4AF37` (Chinese gold) |
| **Accent B** | `#C4762A` (copper bronze) |
| **Accent C** | `#2D6B8A` (cool blue contrast) |
| **Background Override** | `#FDF8F2` (warm rice-paper white, replaces default `#FFFFFF`) |
| **CJK Title Font** | SimSun Bold |
| **CJK Body Font** | Microsoft YaHei |
| **Latin Title Font** | Palatino Linotype Bold |
| **Latin Body Font** | Corbel |
| **Image Keywords** | red lantern, Chinese architecture, traditional culture, festival, gold ornament, calligraphy, temple, Spring Festival |
| **Mask Color** | `rgba(107,20,20,0.75)` (primary-90 based) |
**Warm background notes**: Uses warm rice-paper white `#FDF8F2` instead of pure white:
- `background` = `#FDF8F2`, `surface` = `#F5EDE0` (warm tint), `surface-card` = `#FEFDFB` (near-white card)
- Avoid pure white elements that would look jarring against the warm base
Color Scale:
| Scale | Color Value | Usage |
|------|------|---------|
| primary-100 | `#450D0D` | Deepest background / dramatic pages |
| primary-90 | `#6B1414` | Title bar background |
| primary-80 | `#8B1A1A` | Title text / primary elements |
| primary-60 | `#B84040` | Subtitle / icons |
| primary-40 | `#D57070` | Secondary text |
| primary-20 | `#EDB0B0` | Light decoration |
| primary-10 | `#F8E0E0` | Card background / border |
| primary-5 | `#FDF4F4` | Surface base color |
---
## Custom Themes
If the user specifies a particular color, create a custom theme following these steps:
1. Use the user-specified color as `primary-80`
2. Derive the full 8-level color scale according to the color scale generation rules in section 3.1 of `design-system.md`
3. Select an Accent color with a hue difference of ≥ 30° from the Primary (to ensure visual distinction). Recommended range: 60°180°. Provide 3 accent variants (A/B/C) for variety.
4. Choose the most suitable font pairing from the presets, or use the user-specified fonts
5. Record the complete configuration in comments within the generated code to ensure consistency across the entire PPT deck
## Font Pairing Notes
Each theme has **4 font roles**:
| Role | HTML font-family Syntax | Usage |
|------|----------------------|------|
| CJK Title | Write PPT font name directly: `font-family:'SimHei','Microsoft YaHei',sans-serif` | h1, h2, cover title |
| CJK Body | Write PPT font name directly: `font-family:'Microsoft YaHei',sans-serif` | body, lists, annotations |
| Latin Title | Write PPT font name directly: `font-family:'Century Gothic','Corbel',sans-serif` | Pure Latin character titles |
| Latin Body | Write PPT font name directly: `font-family:'Corbel',sans-serif` | Pure Latin character body text |
**v3 Smart Font Mapping**: html2pptx.js automatically handles fonts:
- **PPT-safe fonts** (SimHei, Corbel, Palatino Linotype, etc. 40+) → Passed through directly, preserved as-is
- **macOS-exclusive fonts** (PingFang, Hiragino) → Automatically mapped to cross-platform equivalent fonts
- **Web fonts** (Roboto, Montserrat, Inter, etc.) → Automatically mapped to the visually closest PPT-safe font
- **fontConfig still available**: Serves as the final fallback default for CJK/Latin
**fontConfig can be passed when calling html2pptx()** (optional, used to override default fallback):
```javascript
const fontConfig = { cjk: 'SimHei', latin: 'Corbel' };
```
**Recommended practice**: Write the target PPT font name directly in HTML; do not rely on fontConfig for switching.
**PPT-safe Chinese fonts**: Microsoft YaHei / SimHei / SimSun / KaiTi / FangSong / DengXian
**PPT-safe English fonts**: Corbel / Arial / Times New Roman / Palatino Linotype / Gill Sans MT / Century Gothic / Garamond / Rockwell / Candara / Constantia / Cambria / Trebuchet MS
---
## Dark Mode Semantic Color Mapping
For themes that need a full dark-mode deck (not just individual dark slides), use these semantic overrides:
| Semantic Token | Light Mode Value | Dark Mode Value |
|---------------|-----------------|-----------------|
| `background` | `#FFFFFF` | `primary-100` |
| `surface` | `primary-5` | `primary-90` |
| `surface-card` | `#FFFFFF` | `primary-80` |
| `text-primary` | `primary-80` | `#FFFFFF` |
| `text-secondary` | `primary-60` | `rgba(255,255,255,0.75)` |
| `text-muted` | `primary-40` | `rgba(255,255,255,0.45)` |
| `border` | `primary-10` | `primary-60` |
| `on-dark` | `#FFFFFF` | `#FFFFFF` (unchanged) |
Deep Mineral and Deep Forest themes already use dark mode by default. For any other theme, apply this mapping to create a dark variant.
Cards in dark mode use `surface-card` background with **no shadow** (shadows invisible on dark backgrounds). Use subtle `border: 1pt solid primary-60` instead for card definition.